Discussion:
[PATCH weston-ivi-shell 00/15] a reference shell for In-Vehicle Infotainment system
(too old to reply)
nobuhiko_tanibata
2014-03-06 09:19:01 UTC
Permalink
Hi,

This patch series adds a reference implementation of a shell for
In-Vehicle Infotainment system; IVI, libraries on the shell to manage
layout of User interface; UI, and samples how to use them. Before
stepping in overview of patches, please let me explain background and
purpose of this contribution.

Background)
I am working for prototyping a shell for In-Vehicle Infotainment; IVI in
TIZEN IVI. This prototyping is being integrated to the TIZEN IVI.

https://review.tizen.org/git/?p=profile/ivi/weston-ivi-shell.git;a=summary

I am also working for GENIVI wayland-ivi-extension and several private
projects with several Car Makers to apply a shell to its use case. The
main use case on them is very similar with each other, which is based on
a concept of Layer Management.

http://projects.genivi.org/ivi-layer-management/node/13

Purpose)
I am contributing a reference for common use case of IVI mentioned in
Background to avoid implementing same one for each user. The main use
case is Layer Management to manage properties of surfaces and layer.
Layer is used for grouping surfaces. In this patch series, I am
contributing libweston-layout.so to support Layer management features
with a set of interfaces which are defined based on ivi-layer-management
from GENIVI. With libweston-layout.so, each shell developer of IVI can
easily implement own shell.

Overview)
This patch series are mainly applied to new folder ?ivi-shell? like
?desktop-shell?. This patch series consists of 5 major parts,

- ivi-shell.so : support ivi-application.xml protocol and initialization
of libweston-layout.so. The ivi-application.xml defines simple
interfaces; ?ivi_application::surface_create?. An interface
ivi_application::surface_create? is used to tie ID to wl_surface from
application. In IVI use case, such IDs are predefined at system design
phase to control surface with business logic. For example, TV
application shall be invisible in case of speed restriction.

- libweston-layout.so: this shall be linked to ivi-shell.so to support
layer management APIs internally. These APIs allows us to manage
surfaces and layer by e.g. setting properties; position, visibility,
opacity and rectangle of source to crop, and so on. This APIs internally
uses weston_view as abstraction layer of compositor.

- hmi-controller.so: a reference implementation how to use
libweston-layout.so. It implement several protocols defined by
ivi-hmi-controller.xml,

1/Requesting which surface is a part of User interfaces, e.g. a surface
draw an icon from PNG files. According to request, hmi-controller
layouts specified surfaces on a Screen by using libweston-layout.so.
2/Requesting layout change. There are 4 types of layout for a reference;
tiling, side by side, full screen, and random.
3/Requesting displaying launchers. There are several pages to group
icons which can be selected by motion of input.
4/Requesting animation moving from one page to another by motion of
input.
A reference how to use these protocols are implemented in
hmi-controller-homescreen. A pthread sets up parts of UI and triggers
layout change, showing launchers, and allowing hmi-controller to select
pages of launchers by using ivi-hmi-controller.xml. This can be
implemented in separated process, e.g. desktop-shell.c, as well.

- Supporting ivi-application protocol to example in ?clients? folder.
Add macro to compile ivi-application separately. Basically it uses the
same code. For example, add macro: ENABLE_IVI_CLIENT to simple-egl.c for
compiling weston-simple-egl-ivi at the same time.

- Add reference weston.ini.in for ivi-shell in ivi-shell folder as well.
It is referred by ivi-shell and hmi-controller.so to define several
configurations. E.g. setting cursor, ID of surfaces and layers to be
used by hmi-controller-homescreen, launchers; path to icons, binary, ID
which page they are located.


I am enclosing a pdf for overview of ivi-shell related parts. The pdf
also mentions ivi-controller.so maintained here to keep compatibility
with IVI layer manager.

http://git.projects.genivi.org/?p=wayland-ivi-extension.git;a=summary

It allow GENIVI graphic application to manage surfaces/layer outside of
Weston process. However it is not purpose to do animation. Ideally,
business logic shall be implemented inside of Weston process to reduce
dispatch of process as much as possible.


Best regards,
Nobuhiko
-------------- next part --------------
A non-text attachment was scrubbed...
Name: weston_ivi_shell_contribution.pdf
Type: application/pdf
Size: 103516 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20140306/f4f60a84/attachment-0001.pdf>
Nobuhiko Tanibata
2014-03-06 09:51:15 UTC
Permalink
From: Kristian H?gsberg <krh at bitplanet.net>

---
src/compositor.h | 3 +++
src/gl-renderer.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)

diff --git a/src/compositor.h b/src/compositor.h
index 22a485f..ace75da 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -540,6 +540,9 @@ struct weston_renderer {
pixman_format_code_t format, void *pixels,
uint32_t x, uint32_t y,
uint32_t width, uint32_t height);
+ int (*read_surface_pixels)(struct weston_surface *es,
+ pixman_format_code_t format, void *pixels,
+ int x, int y, int width, int height);
void (*repaint_output)(struct weston_output *output,
pixman_region32_t *output_damage);
void (*flush_damage)(struct weston_surface *surface);
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 0e5afbe..dca2e05 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -106,6 +106,8 @@ struct gl_renderer {
EGLContext egl_context;
EGLConfig egl_config;

+ GLuint fbo;
+
struct wl_array vertices;
struct wl_array vtxcnt;

@@ -585,6 +587,54 @@ out:
pixman_region32_fini(&repaint);
}

+static int
+gl_renderer_read_surface_pixels(struct weston_surface *es,
+ pixman_format_code_t format, void *pixels,
+ int x, int y, int width, int height)
+{
+ struct weston_buffer *buffer = es->buffer_ref.buffer;
+ struct weston_compositor *ec = es->compositor;
+ struct gl_renderer *gr = get_renderer(ec);
+ struct gl_surface_state *gs = get_surface_state(es);
+ GLenum gl_format;
+ int size;
+ struct wl_shm_buffer *shm_buffer = NULL;
+
+ switch (format) {
+ case PIXMAN_a8r8g8b8:
+ gl_format = GL_BGRA_EXT;
+ break;
+ case PIXMAN_a8b8g8r8:
+ gl_format = GL_RGBA;
+ break;
+ default:
+ return -1;
+ }
+
+ if (buffer) {
+ shm_buffer = wl_shm_buffer_get(buffer->resource);
+ }
+ if (shm_buffer) {
+ size = buffer->width * 4 * buffer->height;
+ memcpy(pixels, wl_shm_buffer_get_data(shm_buffer), size);
+ } else {
+ if (gr->fbo == 0)
+ glGenFramebuffers(1, &gr->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, gr->fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ gs->textures[0], 0);
+
+ glReadPixels(x, y, width, height,
+ gl_format, GL_UNSIGNED_BYTE, pixels);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ return 0;
+}
+
static void
repaint_views(struct weston_output *output, pixman_region32_t *damage)
{
@@ -1602,6 +1652,9 @@ gl_renderer_destroy(struct weston_compositor *ec)

wl_signal_emit(&gr->destroy_signal, gr);

+ if (gr->fbo)
+ glDeleteFramebuffers(1, &gr->fbo);
+
if (gr->has_bind_display)
gr->unbind_display(gr->egl_display, ec->wl_display);

@@ -1699,6 +1752,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
return -1;

gr->base.read_pixels = gl_renderer_read_pixels;
+ gr->base.read_surface_pixels = gl_renderer_read_surface_pixels;
gr->base.repaint_output = gl_renderer_repaint_output;
gr->base.flush_damage = gl_renderer_flush_damage;
gr->base.attach = gl_renderer_attach;
--
1.8.3.1
Pekka Paalanen
2014-03-10 08:10:22 UTC
Permalink
On Thu, 6 Mar 2014 18:51:15 +0900
Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:

> From: Kristian H?gsberg <krh at bitplanet.net>
>
> ---
> src/compositor.h | 3 +++
> src/gl-renderer.c | 54
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files
> changed, 57 insertions(+)
>
> diff --git a/src/compositor.h b/src/compositor.h
> index 22a485f..ace75da 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -540,6 +540,9 @@ struct weston_renderer {
> pixman_format_code_t format, void
> *pixels, uint32_t x, uint32_t y,
> uint32_t width, uint32_t height);
> + int (*read_surface_pixels)(struct weston_surface *es,
> + pixman_format_code_t format, void
> *pixels,
> + int x, int y, int width, int
> height); void (*repaint_output)(struct weston_output *output,
> pixman_region32_t *output_damage);
> void (*flush_damage)(struct weston_surface *surface);
> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
> index 0e5afbe..dca2e05 100644
> --- a/src/gl-renderer.c
> +++ b/src/gl-renderer.c
> @@ -106,6 +106,8 @@ struct gl_renderer {
> EGLContext egl_context;
> EGLConfig egl_config;
>
> + GLuint fbo;
> +
> struct wl_array vertices;
> struct wl_array vtxcnt;
>
> @@ -585,6 +587,54 @@ out:
> pixman_region32_fini(&repaint);
> }
>
> +static int
> +gl_renderer_read_surface_pixels(struct weston_surface *es,
> + pixman_format_code_t format, void
> *pixels,
> + int x, int y, int width, int height)
> +{
> + struct weston_buffer *buffer = es->buffer_ref.buffer;
> + struct weston_compositor *ec = es->compositor;
> + struct gl_renderer *gr = get_renderer(ec);
> + struct gl_surface_state *gs = get_surface_state(es);
> + GLenum gl_format;
> + int size;
> + struct wl_shm_buffer *shm_buffer = NULL;
> +
> + switch (format) {
> + case PIXMAN_a8r8g8b8:
> + gl_format = GL_BGRA_EXT;
> + break;
> + case PIXMAN_a8b8g8r8:
> + gl_format = GL_RGBA;
> + break;
> + default:
> + return -1;
> + }
> +
> + if (buffer) {
> + shm_buffer = wl_shm_buffer_get(buffer->resource);
> + }
> + if (shm_buffer) {
> + size = buffer->width * 4 * buffer->height;
> + memcpy(pixels, wl_shm_buffer_get_data(shm_buffer),
> size);

This branch completely ignores format, x, y, width, and height function
parameters, most likely corrupting random memory. This also assumes 4
bytes per pixel in the shm_buffer, which may not be true.


Thanks,
pq

> + } else {
> + if (gr->fbo == 0)
> + glGenFramebuffers(1, &gr->fbo);
> + glBindFramebuffer(GL_FRAMEBUFFER, gr->fbo);
> + glFramebufferTexture2D(GL_FRAMEBUFFER,
> + GL_COLOR_ATTACHMENT0,
> + GL_TEXTURE_2D,
> + gs->textures[0], 0);
> +
> + glReadPixels(x, y, width, height,
> + gl_format, GL_UNSIGNED_BYTE, pixels);
> +
> + glBindFramebuffer(GL_FRAMEBUFFER, 0);
> + }
> +
> + return 0;
> +}
> +
> static void
> repaint_views(struct weston_output *output, pixman_region32_t
> *damage) {
> @@ -1602,6 +1652,9 @@ gl_renderer_destroy(struct weston_compositor
> *ec)
> wl_signal_emit(&gr->destroy_signal, gr);
>
> + if (gr->fbo)
> + glDeleteFramebuffers(1, &gr->fbo);
> +
> if (gr->has_bind_display)
> gr->unbind_display(gr->egl_display, ec->wl_display);
>
> @@ -1699,6 +1752,7 @@ gl_renderer_create(struct weston_compositor
> *ec, EGLNativeDisplayType display, return -1;
>
> gr->base.read_pixels = gl_renderer_read_pixels;
> + gr->base.read_surface_pixels =
> gl_renderer_read_surface_pixels; gr->base.repaint_output =
> gl_renderer_repaint_output; gr->base.flush_damage =
> gl_renderer_flush_damage; gr->base.attach = gl_renderer_attach;
Nobuhiko Tanibata
2014-03-12 14:46:35 UTC
Permalink
Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- gl_renderer_read_shmbuffer_pixels to support different types of format of
shmbuffer.

src/compositor.h | 3 ++
src/gl-renderer.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+)

diff --git a/src/compositor.h b/src/compositor.h
index 22a485f..ace75da 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -540,6 +540,9 @@ struct weston_renderer {
pixman_format_code_t format, void *pixels,
uint32_t x, uint32_t y,
uint32_t width, uint32_t height);
+ int (*read_surface_pixels)(struct weston_surface *es,
+ pixman_format_code_t format, void *pixels,
+ int x, int y, int width, int height);
void (*repaint_output)(struct weston_output *output,
pixman_region32_t *output_damage);
void (*flush_damage)(struct weston_surface *surface);
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 0e5afbe..7881fd8 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -106,6 +106,8 @@ struct gl_renderer {
EGLContext egl_context;
EGLConfig egl_config;

+ GLuint fbo;
+
struct wl_array vertices;
struct wl_array vtxcnt;

@@ -585,6 +587,114 @@ out:
pixman_region32_fini(&repaint);
}

+static int
+gl_renderer_read_shmbuffer_pixels(struct wl_shm_buffer *shm_buffer,
+ void *pixels, int x, int y, int width, int height)
+{
+ int i;
+ int pixel_size = 0;
+ uint8_t *ptr = NULL;
+ int32_t src_width, src_height, src_stride;
+ int32_t dst_stride;
+ int32_t offset;
+
+ /* Get some parameters of wl_shm_buffer. */
+ src_width = wl_shm_buffer_get_width(shm_buffer);
+ src_height = wl_shm_buffer_get_height(shm_buffer);
+ src_stride = wl_shm_buffer_get_stride(shm_buffer);
+
+ assert((src_width > 0) && (src_height > 0));
+ if ((src_width <= 0) || (src_height <= 0))
+ return -1;
+
+ /* the start of reading position has to be changed. */
+ ptr = wl_shm_buffer_get_data(shm_buffer);
+ ptr += y * src_stride;
+ if ((x == 0) && (width == src_width) && (height <= (src_height - y))) {
+ /* If x is 0 and widths are the same,
+ * whole pixel can be copied in only one time.
+ */
+ memcpy(pixels, ptr, src_stride * height);
+ } else {
+ /* If x is not 0,
+ * every line have to be copied one by one.
+ */
+ pixel_size = src_stride / src_width;
+ assert(pixel_size < 5);
+ if (pixel_size > 4) return -1;
+
+ dst_stride = width * pixel_size;
+ offset = x * pixel_size;
+
+ for (i = 0; i < height; i++, ptr += src_stride) {
+ memcpy(pixels, ptr + offset, dst_stride);
+ pixels = (uint8_t*)pixels + dst_stride;
+ }
+ }
+
+ return 0;
+}
+
+static int
+gl_renderer_read_glsurface_pixels(struct weston_surface *es,
+ pixman_format_code_t format, void *pixels,
+ int x, int y, int width, int height)
+{
+ struct weston_compositor *ec = es->compositor;
+ struct gl_renderer *gr = get_renderer(ec);
+ struct gl_surface_state *gs = get_surface_state(es);
+ GLenum gl_format;
+
+ switch (format) {
+ case PIXMAN_a8r8g8b8:
+ gl_format = GL_BGRA_EXT;
+ break;
+ case PIXMAN_a8b8g8r8:
+ gl_format = GL_RGBA;
+ break;
+ default:
+ return -1;
+ }
+
+ if (gr->fbo == 0)
+ glGenFramebuffers(1, &gr->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, gr->fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ gs->textures[0], 0);
+
+ glReadPixels(x, y, width, height,
+ gl_format, GL_UNSIGNED_BYTE, pixels);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return 0;
+}
+
+static int
+gl_renderer_read_surface_pixels(struct weston_surface *es,
+ pixman_format_code_t format, void *pixels,
+ int x, int y, int width, int height)
+{
+ struct weston_buffer *buffer = es->buffer_ref.buffer;
+ struct wl_shm_buffer *shm_buffer = NULL;
+ int ret = 0;
+
+ if (buffer) {
+ shm_buffer = wl_shm_buffer_get(buffer->resource);
+ }
+ if (shm_buffer) {
+ ret = gl_renderer_read_shmbuffer_pixels(shm_buffer,
+ pixels, x, y, width, height);
+ } else {
+ ret = gl_renderer_read_glsurface_pixels(es,
+ format, pixels, x, y, width, height);
+ }
+
+ return ret;
+}
+
static void
repaint_views(struct weston_output *output, pixman_region32_t *damage)
{
@@ -1602,6 +1712,9 @@ gl_renderer_destroy(struct weston_compositor *ec)

wl_signal_emit(&gr->destroy_signal, gr);

+ if (gr->fbo)
+ glDeleteFramebuffers(1, &gr->fbo);
+
if (gr->has_bind_display)
gr->unbind_display(gr->egl_display, ec->wl_display);

@@ -1699,6 +1812,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
return -1;

gr->base.read_pixels = gl_renderer_read_pixels;
+ gr->base.read_surface_pixels = gl_renderer_read_surface_pixels;
gr->base.repaint_output = gl_renderer_repaint_output;
gr->base.flush_damage = gl_renderer_flush_damage;
gr->base.attach = gl_renderer_attach;
--
1.8.3.1
Pekka Paalanen
2014-03-13 08:47:03 UTC
Permalink
On Wed, 12 Mar 2014 23:46:35 +0900
Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:

> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> ---
>
> Changes for v2:
> - gl_renderer_read_shmbuffer_pixels to support different types of format of
> shmbuffer.
>
> src/compositor.h | 3 ++
> src/gl-renderer.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 117 insertions(+)
>
> diff --git a/src/compositor.h b/src/compositor.h
> index 22a485f..ace75da 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -540,6 +540,9 @@ struct weston_renderer {
> pixman_format_code_t format, void *pixels,
> uint32_t x, uint32_t y,
> uint32_t width, uint32_t height);
> + int (*read_surface_pixels)(struct weston_surface *es,
> + pixman_format_code_t format, void *pixels,
> + int x, int y, int width, int height);
> void (*repaint_output)(struct weston_output *output,
> pixman_region32_t *output_damage);
> void (*flush_damage)(struct weston_surface *surface);
> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
> index 0e5afbe..7881fd8 100644
> --- a/src/gl-renderer.c
> +++ b/src/gl-renderer.c
> @@ -106,6 +106,8 @@ struct gl_renderer {
> EGLContext egl_context;
> EGLConfig egl_config;
>
> + GLuint fbo;
> +
> struct wl_array vertices;
> struct wl_array vtxcnt;
>
> @@ -585,6 +587,114 @@ out:
> pixman_region32_fini(&repaint);
> }
>
> +static int
> +gl_renderer_read_shmbuffer_pixels(struct wl_shm_buffer *shm_buffer,
> + void *pixels, int x, int y, int width, int height)

How is 'pixels' allocated, what should we assume?

Is the size of the 'pixels' buffer as width*height*4 bytes, with
stride=width*4 bytes?

What do we assume about the 'pixels' color format?

What if the shm_buffer has color format RGB565?

What if shm_buffer stride is more than width*4 bytes?

But, see below.

> +{
> + int i;
> + int pixel_size = 0;
> + uint8_t *ptr = NULL;
> + int32_t src_width, src_height, src_stride;
> + int32_t dst_stride;
> + int32_t offset;
> +
> + /* Get some parameters of wl_shm_buffer. */
> + src_width = wl_shm_buffer_get_width(shm_buffer);
> + src_height = wl_shm_buffer_get_height(shm_buffer);
> + src_stride = wl_shm_buffer_get_stride(shm_buffer);
> +
> + assert((src_width > 0) && (src_height > 0));
> + if ((src_width <= 0) || (src_height <= 0))
> + return -1;
> +
> + /* the start of reading position has to be changed. */
> + ptr = wl_shm_buffer_get_data(shm_buffer);
> + ptr += y * src_stride;
> + if ((x == 0) && (width == src_width) && (height <= (src_height - y))) {
> + /* If x is 0 and widths are the same,
> + * whole pixel can be copied in only one time.
> + */
> + memcpy(pixels, ptr, src_stride * height);
> + } else {
> + /* If x is not 0,
> + * every line have to be copied one by one.
> + */
> + pixel_size = src_stride / src_width;
> + assert(pixel_size < 5);
> + if (pixel_size > 4) return -1;
> +
> + dst_stride = width * pixel_size;
> + offset = x * pixel_size;
> +
> + for (i = 0; i < height; i++, ptr += src_stride) {
> + memcpy(pixels, ptr + offset, dst_stride);
> + pixels = (uint8_t*)pixels + dst_stride;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int
> +gl_renderer_read_glsurface_pixels(struct weston_surface *es,
> + pixman_format_code_t format, void *pixels,
> + int x, int y, int width, int height)
> +{
> + struct weston_compositor *ec = es->compositor;
> + struct gl_renderer *gr = get_renderer(ec);
> + struct gl_surface_state *gs = get_surface_state(es);
> + GLenum gl_format;
> +
> + switch (format) {
> + case PIXMAN_a8r8g8b8:
> + gl_format = GL_BGRA_EXT;
> + break;
> + case PIXMAN_a8b8g8r8:
> + gl_format = GL_RGBA;
> + break;
> + default:
> + return -1;
> + }
> +
> + if (gr->fbo == 0)
> + glGenFramebuffers(1, &gr->fbo);
> + glBindFramebuffer(GL_FRAMEBUFFER, gr->fbo);
> + glFramebufferTexture2D(GL_FRAMEBUFFER,
> + GL_COLOR_ATTACHMENT0,
> + GL_TEXTURE_2D,
> + gs->textures[0], 0);
> +
> + glReadPixels(x, y, width, height,
> + gl_format, GL_UNSIGNED_BYTE, pixels);
> +
> + glBindFramebuffer(GL_FRAMEBUFFER, 0);
> +
> + return 0;
> +}
> +
> +static int
> +gl_renderer_read_surface_pixels(struct weston_surface *es,
> + pixman_format_code_t format, void *pixels,
> + int x, int y, int width, int height)
> +{
> + struct weston_buffer *buffer = es->buffer_ref.buffer;
> + struct wl_shm_buffer *shm_buffer = NULL;
> + int ret = 0;
> +
> + if (buffer) {
> + shm_buffer = wl_shm_buffer_get(buffer->resource);
> + }
> + if (shm_buffer) {
> + ret = gl_renderer_read_shmbuffer_pixels(shm_buffer,
> + pixels, x, y, width, height);
> + } else {
> + ret = gl_renderer_read_glsurface_pixels(es,
> + format, pixels, x, y, width, height);
> + }

I just realized that we are dealing with the GL-renderer only here.
That means that the surface will always have a GL texture, which you
can read back, regardless of if the original wl_buffer was wl_shm or
EGL based.

Therefore I think you could remove the whole shm path. I suppose
optimizing the shm read-back path is not too useful, right?

That is also the reason why you would probably never hit the shm case
to begin with. GL-renderer releases the wl_buffer as soon as it has
copied its content into a texture, so the buffer pointer is likely
always NULL.

Sorry for not realizing that earlier.

So just one more question: what about YUV color formats? That's why
gl_surface_state has an array of textures instead of just one. YUV data
can come in via EGL based buffers. You could at least return failure
for unhandled color formats, maybe?


Thanks,
pq

> +
> + return ret;
> +}
> +
> static void
> repaint_views(struct weston_output *output, pixman_region32_t *damage)
> {
> @@ -1602,6 +1712,9 @@ gl_renderer_destroy(struct weston_compositor *ec)
>
> wl_signal_emit(&gr->destroy_signal, gr);
>
> + if (gr->fbo)
> + glDeleteFramebuffers(1, &gr->fbo);
> +
> if (gr->has_bind_display)
> gr->unbind_display(gr->egl_display, ec->wl_display);
>
> @@ -1699,6 +1812,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
> return -1;
>
> gr->base.read_pixels = gl_renderer_read_pixels;
> + gr->base.read_surface_pixels = gl_renderer_read_surface_pixels;
> gr->base.repaint_output = gl_renderer_repaint_output;
> gr->base.flush_damage = gl_renderer_flush_damage;
> gr->base.attach = gl_renderer_attach;
Nobuhiko Tanibata
2014-03-14 12:29:36 UTC
Permalink
2014-03-13 17:47 ? Pekka Paalanen ????????:
> On Wed, 12 Mar 2014 23:46:35 +0900
> Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>
>> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
>> ---
>>
>> Changes for v2:
>> - gl_renderer_read_shmbuffer_pixels to support different types of
>> format of
>> shmbuffer.
>>
>> src/compositor.h | 3 ++
>> src/gl-renderer.c | 114
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 117 insertions(+)
>>
>> diff --git a/src/compositor.h b/src/compositor.h
>> index 22a485f..ace75da 100644
>> --- a/src/compositor.h
>> +++ b/src/compositor.h
>> @@ -540,6 +540,9 @@ struct weston_renderer {
>> pixman_format_code_t format, void *pixels,
>> uint32_t x, uint32_t y,
>> uint32_t width, uint32_t height);
>> + int (*read_surface_pixels)(struct weston_surface *es,
>> + pixman_format_code_t format, void *pixels,
>> + int x, int y, int width, int height);
>> void (*repaint_output)(struct weston_output *output,
>> pixman_region32_t *output_damage);
>> void (*flush_damage)(struct weston_surface *surface);
>> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
>> index 0e5afbe..7881fd8 100644
>> --- a/src/gl-renderer.c
>> +++ b/src/gl-renderer.c
>> @@ -106,6 +106,8 @@ struct gl_renderer {
>> EGLContext egl_context;
>> EGLConfig egl_config;
>>
>> + GLuint fbo;
>> +
>> struct wl_array vertices;
>> struct wl_array vtxcnt;
>>
>> @@ -585,6 +587,114 @@ out:
>> pixman_region32_fini(&repaint);
>> }
>>
>> +static int
>> +gl_renderer_read_shmbuffer_pixels(struct wl_shm_buffer *shm_buffer,
>> + void *pixels, int x, int y, int width, int height)
>
> How is 'pixels' allocated, what should we assume?
>
> Is the size of the 'pixels' buffer as width*height*4 bytes, with
> stride=width*4 bytes?
>
> What do we assume about the 'pixels' color format?
>
> What if the shm_buffer has color format RGB565?
>
> What if shm_buffer stride is more than width*4 bytes?
>
> But, see below.
>
>> +{
>> + int i;
>> + int pixel_size = 0;
>> + uint8_t *ptr = NULL;
>> + int32_t src_width, src_height, src_stride;
>> + int32_t dst_stride;
>> + int32_t offset;
>> +
>> + /* Get some parameters of wl_shm_buffer. */
>> + src_width = wl_shm_buffer_get_width(shm_buffer);
>> + src_height = wl_shm_buffer_get_height(shm_buffer);
>> + src_stride = wl_shm_buffer_get_stride(shm_buffer);
>> +
>> + assert((src_width > 0) && (src_height > 0));
>> + if ((src_width <= 0) || (src_height <= 0))
>> + return -1;
>> +
>> + /* the start of reading position has to be changed. */
>> + ptr = wl_shm_buffer_get_data(shm_buffer);
>> + ptr += y * src_stride;
>> + if ((x == 0) && (width == src_width) && (height <= (src_height -
>> y))) {
>> + /* If x is 0 and widths are the same,
>> + * whole pixel can be copied in only one time.
>> + */
>> + memcpy(pixels, ptr, src_stride * height);
>> + } else {
>> + /* If x is not 0,
>> + * every line have to be copied one by one.
>> + */
>> + pixel_size = src_stride / src_width;
>> + assert(pixel_size < 5);
>> + if (pixel_size > 4) return -1;
>> +
>> + dst_stride = width * pixel_size;
>> + offset = x * pixel_size;
>> +
>> + for (i = 0; i < height; i++, ptr += src_stride) {
>> + memcpy(pixels, ptr + offset, dst_stride);
>> + pixels = (uint8_t*)pixels + dst_stride;
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int
>> +gl_renderer_read_glsurface_pixels(struct weston_surface *es,
>> + pixman_format_code_t format, void *pixels,
>> + int x, int y, int width, int height)
>> +{
>> + struct weston_compositor *ec = es->compositor;
>> + struct gl_renderer *gr = get_renderer(ec);
>> + struct gl_surface_state *gs = get_surface_state(es);
>> + GLenum gl_format;
>> +
>> + switch (format) {
>> + case PIXMAN_a8r8g8b8:
>> + gl_format = GL_BGRA_EXT;
>> + break;
>> + case PIXMAN_a8b8g8r8:
>> + gl_format = GL_RGBA;
>> + break;
>> + default:
>> + return -1;
>> + }
>> +
>> + if (gr->fbo == 0)
>> + glGenFramebuffers(1, &gr->fbo);
>> + glBindFramebuffer(GL_FRAMEBUFFER, gr->fbo);
>> + glFramebufferTexture2D(GL_FRAMEBUFFER,
>> + GL_COLOR_ATTACHMENT0,
>> + GL_TEXTURE_2D,
>> + gs->textures[0], 0);
>> +
>> + glReadPixels(x, y, width, height,
>> + gl_format, GL_UNSIGNED_BYTE, pixels);
>> +
>> + glBindFramebuffer(GL_FRAMEBUFFER, 0);
>> +
>> + return 0;
>> +}
>> +
>> +static int
>> +gl_renderer_read_surface_pixels(struct weston_surface *es,
>> + pixman_format_code_t format, void *pixels,
>> + int x, int y, int width, int height)
>> +{
>> + struct weston_buffer *buffer = es->buffer_ref.buffer;
>> + struct wl_shm_buffer *shm_buffer = NULL;
>> + int ret = 0;
>> +
>> + if (buffer) {
>> + shm_buffer = wl_shm_buffer_get(buffer->resource);
>> + }
>> + if (shm_buffer) {
>> + ret = gl_renderer_read_shmbuffer_pixels(shm_buffer,
>> + pixels, x, y, width, height);
>> + } else {
>> + ret = gl_renderer_read_glsurface_pixels(es,
>> + format, pixels, x, y, width, height);
>> + }
>
> I just realized that we are dealing with the GL-renderer only here.
> That means that the surface will always have a GL texture, which you
> can read back, regardless of if the original wl_buffer was wl_shm or
> EGL based.
>

Hi pq,

Thanks, it is very useful comment.

Yes, you are right. I thought I try to remove wl_shm patch to release
this patch at once
according to your comment
However, as you mention below, I also think how to handle YUV format.
This
format, YUV, is a important in Automotive for handling capture of e.g.
Back
Guide monitor as well. So I need time to discuss more internally. So I
drop this patch
to rethink more.
And I will remove parts calling gl_renderer_read_surface_pixels in
westion_layout
to support capture snapshot per a surface. This is not mandatory to
support for the time being.

BR,
Nobuhiko

> Therefore I think you could remove the whole shm path. I suppose
> optimizing the shm read-back path is not too useful, right?
>
> That is also the reason why you would probably never hit the shm case
> to begin with. GL-renderer releases the wl_buffer as soon as it has
> copied its content into a texture, so the buffer pointer is likely
> always NULL.
>
> Sorry for not realizing that earlier.
>
> So just one more question: what about YUV color formats? That's why
> gl_surface_state has an array of textures instead of just one. YUV data
> can come in via EGL based buffers. You could at least return failure
> for unhandled color formats, maybe?
>
>
> Thanks,
> pq
>
>> +
>> + return ret;
>> +}
>> +
>> static void
>> repaint_views(struct weston_output *output, pixman_region32_t
>> *damage)
>> {
>> @@ -1602,6 +1712,9 @@ gl_renderer_destroy(struct weston_compositor
>> *ec)
>>
>> wl_signal_emit(&gr->destroy_signal, gr);
>>
>> + if (gr->fbo)
>> + glDeleteFramebuffers(1, &gr->fbo);
>> +
>> if (gr->has_bind_display)
>> gr->unbind_display(gr->egl_display, ec->wl_display);
>>
>> @@ -1699,6 +1812,7 @@ gl_renderer_create(struct weston_compositor *ec,
>> EGLNativeDisplayType display,
>> return -1;
>>
>> gr->base.read_pixels = gl_renderer_read_pixels;
>> + gr->base.read_surface_pixels = gl_renderer_read_surface_pixels;
>> gr->base.repaint_output = gl_renderer_repaint_output;
>> gr->base.flush_damage = gl_renderer_flush_damage;
>> gr->base.attach = gl_renderer_attach;
Nobuhiko Tanibata
2014-03-06 09:53:08 UTC
Permalink
Add interface ivi_application, which creates ivi_surface objects tied
to a given wl_surface with a given id. The given id can be used in a
shell to identify which application is assigned to a wl_surface and
layout the surface wherever the shell wants. ivi_surface objects can
be used to receive status of wl_surface in the scenegraph of the
compositor.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
protocol/ivi-application.xml | 88 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 protocol/ivi-application.xml

diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
new file mode 100644
index 0000000..e58ad26
--- /dev/null
+++ b/protocol/ivi-application.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ivi_application">
+
+ <copyright>
+ Copyright (C) 2013 DENSO CORPORATION
+ Copyright (c) 2013 BMW Car IT GmbH
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ </copyright>
+
+ <interface name="ivi_surface" version="1">
+ <description summary="application interface to surface in ivi compositor"/>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy ivi_surface"/>
+ </request>
+
+ <event name="visibility">
+ <description summary="visibility of surface in ivi compositor has changed">
+ The new visibility state is provided in argument visibility.
+ If visibility is 0, the surface has become invisible.
+ If visibility is not 0, the surface has become visible.
+ </description>
+ <arg name="visibility" type="int"/>
+ </event>
+
+ </interface>
+
+ <interface name="ivi_application" version="1">
+ <description summary="interface for ivi applications to use ivi compositor features"/>
+
+ <request name="surface_create">
+ <description summary="create surface in ivi compositor">
+ surface_create will create a new surface with surface_id in ivi compositor,
+ if it does not yet exists. If the surface with surface_id already exists in
+ ivi compositor, the application content provided in argument surface will
+ be used as surface content. If an other ivi application already registered
+ content for surface with surface_id, an error event will indicate the problem.
+ </description>
+ <arg name="id_surface" type="uint"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="id" type="new_id" interface="ivi_surface"/>
+ </request>
+
+ <enum name="error_code">
+ <description summary="possible error codes returned by ivi compositor">
+ These error codes define all possible error codes returned by ivi compositor
+ on server-side errors.
+ </description>
+ <entry name="unknown_error" value="1" summary="unknown error encountered"/>
+ <entry name="resource_in_use" value="2" summary="resource is in use and can not be shared"/>
+ </enum>
+
+ <event name="error">
+ <description summary="server-side error detected">
+ The ivi compositor encountered error while processing a request by this
+ application. The error is defined by argument error_code and optional
+ error_text.
+ If the application requires to associate this error event to a request,
+ it can
+ 1. send request
+ 2. force display roundtrip
+ 3. check, if error event was received
+ but this restricts the application to have only one open request at a time.
+ </description>
+ <arg name="error_code" type="int"/>
+ <arg name="error_text" type="string" allow-null="true"/>
+ </event>
+
+ </interface>
+
+</protocol>
--
1.8.3.1
Jason Ekstrand
2014-03-06 15:21:39 UTC
Permalink
On Mar 6, 2014 3:53 AM, "Nobuhiko Tanibata" <
NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>
> Add interface ivi_application, which creates ivi_surface objects tied
> to a given wl_surface with a given id. The given id can be used in a
> shell to identify which application is assigned to a wl_surface and
> layout the surface wherever the shell wants. ivi_surface objects can
> be used to receive status of wl_surface in the scenegraph of the
> compositor.

In general, I think this looks pretty good. It's nice and simple and only
adds what's needed for clients. I do have a couple comments below.
--Jason Ekstrand

>
> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> ---
> protocol/ivi-application.xml | 88
++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 88 insertions(+)
> create mode 100644 protocol/ivi-application.xml
>
> diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
> new file mode 100644
> index 0000000..e58ad26
> --- /dev/null
> +++ b/protocol/ivi-application.xml
> @@ -0,0 +1,88 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<protocol name="ivi_application">
> +
> + <copyright>
> + Copyright (C) 2013 DENSO CORPORATION
> + Copyright (c) 2013 BMW Car IT GmbH
> +
> + Permission is hereby granted, free of charge, to any person
obtaining a copy
> + of this software and associated documentation files (the
"Software"), to deal
> + in the Software without restriction, including without limitation
the rights
> + to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
> + copies of the Software, and to permit persons to whom the Software is
> + furnished to do so, subject to the following conditions:
> +
> + The above copyright notice and this permission notice shall be
included in
> + all copies or substantial portions of the Software.
> +
> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
> + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
> + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
> + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
> + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
> + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
> + THE SOFTWARE.
> + </copyright>
> +
> + <interface name="ivi_surface" version="1">
> + <description summary="application interface to surface in ivi
compositor"/>
> +
> + <request name="destroy" type="destructor">
> + <description summary="destroy ivi_surface"/>
> + </request>
> +
> + <event name="visibility">
> + <description summary="visibility of surface in ivi
compositor has changed">
> + The new visibility state is provided in argument
visibility.
> + If visibility is 0, the surface has become invisible.
> + If visibility is not 0, the surface has become visible.
> + </description>
> + <arg name="visibility" type="int"/>
> + </event>
> +
> + </interface>
> +
> + <interface name="ivi_application" version="1">
> + <description summary="interface for ivi applications to use ivi
compositor features"/>
> +
> + <request name="surface_create">
> + <description summary="create surface in ivi compositor">
> + surface_create will create a new surface with surface_id
in ivi compositor,
> + if it does not yet exists. If the surface with
surface_id already exists in
> + ivi compositor, the application content provided in
argument surface will
> + be used as surface content. If an other ivi application
already registered
> + content for surface with surface_id, an error event will
indicate the problem.
> + </description>
> + <arg name="id_surface" type="uint"/>
> + <arg name="surface" type="object" interface="wl_surface"/>
> + <arg name="id" type="new_id" interface="ivi_surface"/>
> + </request>
> +
> + <enum name="error_code">
> + <description summary="possible error codes returned by ivi
compositor">
> + These error codes define all possible error codes
returned by ivi compositor
> + on server-side errors.
> + </description>
> + <entry name="unknown_error" value="1" summary="unknown
error encountered"/>

What kinds of things do you use "unknown error" for? I'm not sure how
that's useful to the client.

> + <entry name="resource_in_use" value="2" summary="resource is
in use and can not be shared"/>

What kind of resource does this refer to? It looks like you use it if
someone tries to call surface_create twice on the same surface, but you
don't specify.

> + </enum>
> +
> + <event name="error">
> + <description summary="server-side error detected">
> + The ivi compositor encountered error while processing a
request by this
> + application. The error is defined by argument error_code
and optional
> + error_text.
> + If the application requires to associate this error
event to a request,
> + it can
> + 1. send request
> + 2. force display roundtrip
> + 3. check, if error event was received
> + but this restricts the application to have only one
open request at a time.
> + </description>
> + <arg name="error_code" type="int"/>
> + <arg name="error_text" type="string" allow-null="true"/>
> + </event>

Why are you using this rather than the built-in wl_display.error? The
built-in wl_display.error also terminates the client when an error is
sent. Under what error conditions would you want the client to continue?

> +
> + </interface>
> +
> +</protocol>
> --
> 1.8.3.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20140306/e203a008/attachment.html>
Nobuhiko Tanibata
2014-03-07 01:07:35 UTC
Permalink
2014-03-07 00:21 ? Jason Ekstrand ????????:
> On Mar 6, 2014 3:53 AM, "Nobuhiko Tanibata"
> <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
> >
> > Add interface ivi_application, which creates ivi_surface objects
> tied
> > to a given wl_surface with a given id. The given id can be used in
> a
> > shell to identify which application is assigned to a wl_surface and
> > layout the surface wherever the shell wants. ivi_surface objects
> can
> > be used to receive status of wl_surface in the scenegraph of the
> > compositor.
>
> In general, I think this looks pretty good.? It's nice and simple and
> only adds what's needed for clients.? I do have a couple comments
> below.
> --Jason Ekstrand
>
>>
> > Signed-off-by: Nobuhiko Tanibata
> <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> > ---
> > ?protocol/ivi-application.xml | 88
> ++++++++++++++++++++++++++++++++++++++++++++
> > ?1 file changed, 88 insertions(+)
> > ?create mode 100644 protocol/ivi-application.xml
> >
> > diff --git a/protocol/ivi-application.xml
> b/protocol/ivi-application.xml
> > new file mode 100644
> > index 0000000..e58ad26
> > --- /dev/null
> > +++ b/protocol/ivi-application.xml
> > @@ -0,0 +1,88 @@
> > +<?xml version="1.0" encoding="UTF-8"?>
> > +<protocol name="ivi_application">
> > +
> > + ? ?<copyright>
> > + ? ?Copyright (C) 2013 DENSO CORPORATION
> > + ? ?Copyright (c) 2013 BMW Car IT GmbH
> > +
> > + ? ?Permission is hereby granted, free of charge, to any person
> obtaining a copy
> > + ? ?of this software and associated documentation files (the
> "Software"), to deal
> > + ? ?in the Software without restriction, including without
> limitation the rights
> > + ? ?to use, copy, modify, merge, publish, distribute,
> sublicense, and/or sell
> > + ? ?copies of the Software, and to permit persons to whom the
> Software is
> > + ? ?furnished to do so, subject to the following conditions:
> > +
> > + ? ?The above copyright notice and this permission notice shall
> be included in
> > + ? ?all copies or substantial portions of the Software.
> > +
> > + ? ?THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND, EXPRESS OR
> > + ? ?IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> > + ? ?FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
> EVENT SHALL THE
> > + ? ?AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR OTHER
> > + ? ?LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> OTHERWISE, ARISING FROM,
> > + ? ?OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER DEALINGS IN
> > + ? ?THE SOFTWARE.
> > + ? ?</copyright>
> > +
> > + ? ?<interface name="ivi_surface" version="1">
> > + ? ? ? ?<description summary="application interface to surface
> in ivi compositor"/>
> > +
> > + ? ? ? ?<request name="destroy" type="destructor">
> > + ? ? ? ? ? ?<description summary="destroy ivi_surface"/>
> > + ? ? ? ?</request>
> > +
> > + ? ? ? ?<event name="visibility">
> > + ? ? ? ? ? ?<description summary="visibility of surface in
> ivi compositor has changed">
> > + ? ? ? ? ? ? ? ?The new visibility state is provided in
> argument visibility.
> > + ? ? ? ? ? ? ? ?If visibility is 0, the surface has become
> invisible.
> > + ? ? ? ? ? ? ? ?If visibility is not 0, the surface has
> become visible.
> > + ? ? ? ? ? ?</description>
> > + ? ? ? ? ? ?<arg name="visibility" type="int"/>
> > + ? ? ? ?</event>
> > +
> > + ? ?</interface>
> > +
> > + ? ?<interface name="ivi_application" version="1">
> > + ? ? ? ?<description summary="interface for ivi applications
> to use ivi compositor features"/>
> > +
> > + ? ? ? ?<request name="surface_create">
> > + ? ? ? ? ? ?<description summary="create surface in ivi
> compositor">
> > + ? ? ? ? ? ? ? ?surface_create will create a new surface
> with surface_id in ivi compositor,
> > + ? ? ? ? ? ? ? ?if it does not yet exists. If the surface
> with surface_id already exists in
> > + ? ? ? ? ? ? ? ?ivi compositor, the application content
> provided in argument surface will
> > + ? ? ? ? ? ? ? ?be used as surface content. If an other
> ivi application already registered
> > + ? ? ? ? ? ? ? ?content for surface with surface_id, an
> error event will indicate the problem.
> > + ? ? ? ? ? ?</description>
> > + ? ? ? ? ? ?<arg name="id_surface" type="uint"/>
> > + ? ? ? ? ? ?<arg name="surface" type="object"
> interface="wl_surface"/>
> > + ? ? ? ? ? ?<arg name="id" type="new_id"
> interface="ivi_surface"/>
> > + ? ? ? ?</request>
> > +
> > + ? ? ? ?<enum name="error_code">
> > + ? ? ? ? ? ?<description summary="possible error codes
> returned by ivi compositor">
> > + ? ? ? ? ? ? ? ?These error codes define all possible
> error codes returned by ivi compositor
> > + ? ? ? ? ? ? ? ?on server-side errors.
> > + ? ? ? ? ? ?</description>
> > + ? ? ? ? ? ?<entry name="unknown_error" ? value="1"
> summary="unknown error encountered"/>
>
> What kinds of things do you use "unknown error" for?? I'm not sure
> how that's useful to the client.
>

Hi Jason,

Thank you for reviewing.

I see. From this review point, it shall not return no useful value to
the client.
I break down more here.
- id in use: specified ID for ivi_surface is already used by itself or
other client.
- resource in use: specified ID of wl_surface is already tie to another
ID of ivi_surface.
- invalid resource: specified ID of wl_surface is not valid in server.

I think these three is sufficient for client.

>> + ? ? ? ? ? ?<entry name="resource_in_use" value="2"
> summary="resource is in use and can not be shared"/>
>
> What kind of resource does this refer to?? It looks like you use it
> if someone tries to call surface_create twice on the same surface, but
> you don't specify.
>
>> + ? ? ? ?</enum>
> > +
> > + ? ? ? ?<event name="error">
> > + ? ? ? ? ? ?<description summary="server-side error
> detected">
> > + ? ? ? ? ? ? ? ?The ivi compositor encountered error while
> processing a request by this
> > + ? ? ? ? ? ? ? ?application. The error is defined by
> argument error_code and optional
> > + ? ? ? ? ? ? ? ?error_text.
> > + ? ? ? ? ? ? ? ?If the application requires to associate
> this error event to a request,
> > + ? ? ? ? ? ? ? ?it can
> > + ? ? ? ? ? ? ? ? ? ?1. send request
> > + ? ? ? ? ? ? ? ? ? ?2. force display roundtrip
> > + ? ? ? ? ? ? ? ? ? ?3. check, if error event was
> received
> > + ? ? ? ? ? ? ? ? but this restricts the application to
> have only one open request at a time.
> > + ? ? ? ? ? ?</description>
> > + ? ? ? ? ? ?<arg name="error_code" type="int"/>
> > + ? ? ? ? ? ?<arg name="error_text" type="string"
> allow-null="true"/>
> > + ? ? ? ?</event>
>
> Why are you using this rather than the built-in wl_display.error??
> The built-in wl_display.error also terminates the client when an error
> is sent.? Under what error conditions would you want the client to
> continue?
>

Good suggestion!
According to wayland.xml, error code from 0 to 2 is reserved for global.
Please teach me there is any manner which number I can use for the above
object? In the feature, if wayland.xml updated to add new global error
code to 3, the local number may need to be incremented.

BR,
Nobuhiko
>> +
> > + ? ?</interface>
> > +
> > +</protocol>
> > --
> > 1.8.3.1
> >
> > _______________________________________________
> > wayland-devel mailing list
> > wayland-devel at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel [1]
>
>
> Links:
> ------
> [1] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
Jason Ekstrand
2014-03-07 02:37:07 UTC
Permalink
On Mar 6, 2014 7:08 PM, "Nobuhiko Tanibata" <
nobuhiko_tanibata at xddp.denso.co.jp> wrote:
>
> 2014-03-07 00:21 ? Jason Ekstrand ????????:
>
>> On Mar 6, 2014 3:53 AM, "Nobuhiko Tanibata"
>> <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>> >
>> > Add interface ivi_application, which creates ivi_surface objects
>> tied
>> > to a given wl_surface with a given id. The given id can be used in
>> a
>> > shell to identify which application is assigned to a wl_surface and
>> > layout the surface wherever the shell wants. ivi_surface objects
>> can
>> > be used to receive status of wl_surface in the scenegraph of the
>> > compositor.
>>
>> In general, I think this looks pretty good. It's nice and simple and
>> only adds what's needed for clients. I do have a couple comments
>> below.
>> --Jason Ekstrand
>>
>>>
>> > Signed-off-by: Nobuhiko Tanibata
>> <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
>> > ---
>> > protocol/ivi-application.xml | 88
>> ++++++++++++++++++++++++++++++++++++++++++++
>> > 1 file changed, 88 insertions(+)
>> > create mode 100644 protocol/ivi-application.xml
>> >
>> > diff --git a/protocol/ivi-application.xml
>> b/protocol/ivi-application.xml
>> > new file mode 100644
>> > index 0000000..e58ad26
>> > --- /dev/null
>> > +++ b/protocol/ivi-application.xml
>> > @@ -0,0 +1,88 @@
>> > +<?xml version="1.0" encoding="UTF-8"?>
>> > +<protocol name="ivi_application">
>> > +
>> > + <copyright>
>> > + Copyright (C) 2013 DENSO CORPORATION
>> > + Copyright (c) 2013 BMW Car IT GmbH
>> > +
>> > + Permission is hereby granted, free of charge, to any person
>> obtaining a copy
>> > + of this software and associated documentation files (the
>> "Software"), to deal
>> > + in the Software without restriction, including without
>> limitation the rights
>> > + to use, copy, modify, merge, publish, distribute,
>> sublicense, and/or sell
>> > + copies of the Software, and to permit persons to whom the
>> Software is
>> > + furnished to do so, subject to the following conditions:
>> > +
>> > + The above copyright notice and this permission notice shall
>> be included in
>> > + all copies or substantial portions of the Software.
>> > +
>> > + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
>> KIND, EXPRESS OR
>> > + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> > + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
>> EVENT SHALL THE
>> > + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
>> DAMAGES OR OTHER
>> > + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
>> OTHERWISE, ARISING FROM,
>> > + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> OTHER DEALINGS IN
>> > + THE SOFTWARE.
>> > + </copyright>
>> > +
>> > + <interface name="ivi_surface" version="1">
>> > + <description summary="application interface to surface
>> in ivi compositor"/>
>> > +
>> > + <request name="destroy" type="destructor">
>> > + <description summary="destroy ivi_surface"/>
>> > + </request>
>> > +
>> > + <event name="visibility">
>> > + <description summary="visibility of surface in
>> ivi compositor has changed">
>> > + The new visibility state is provided in
>> argument visibility.
>> > + If visibility is 0, the surface has become
>> invisible.
>> > + If visibility is not 0, the surface has
>> become visible.
>> > + </description>
>> > + <arg name="visibility" type="int"/>
>> > + </event>
>> > +
>> > + </interface>
>> > +
>> > + <interface name="ivi_application" version="1">
>> > + <description summary="interface for ivi applications
>> to use ivi compositor features"/>
>> > +
>> > + <request name="surface_create">
>> > + <description summary="create surface in ivi
>> compositor">
>> > + surface_create will create a new surface
>> with surface_id in ivi compositor,
>> > + if it does not yet exists. If the surface
>> with surface_id already exists in
>> > + ivi compositor, the application content
>> provided in argument surface will
>> > + be used as surface content. If an other
>> ivi application already registered
>> > + content for surface with surface_id, an
>> error event will indicate the problem.
>> > + </description>
>> > + <arg name="id_surface" type="uint"/>
>> > + <arg name="surface" type="object"
>> interface="wl_surface"/>
>> > + <arg name="id" type="new_id"
>> interface="ivi_surface"/>
>> > + </request>
>> > +
>> > + <enum name="error_code">
>> > + <description summary="possible error codes
>> returned by ivi compositor">
>> > + These error codes define all possible
>> error codes returned by ivi compositor
>> > + on server-side errors.
>> > + </description>
>> > + <entry name="unknown_error" value="1"
>> summary="unknown error encountered"/>
>>
>> What kinds of things do you use "unknown error" for? I'm not sure
>> how that's useful to the client.
>>
>
> Hi Jason,
>
> Thank you for reviewing.
>
> I see. From this review point, it shall not return no useful value to the
client.
> I break down more here.
> - id in use: specified ID for ivi_surface is already used by itself or
other client.
> - resource in use: specified ID of wl_surface is already tie to another
ID of ivi_surface.
> - invalid resource: specified ID of wl_surface is not valid in server.
>
> I think these three is sufficient for client.
>
>
>>> + <entry name="resource_in_use" value="2"
>>
>> summary="resource is in use and can not be shared"/>
>>
>> What kind of resource does this refer to? It looks like you use it
>> if someone tries to call surface_create twice on the same surface, but
>> you don't specify.
>>
>>> + </enum>
>>
>> > +
>> > + <event name="error">
>> > + <description summary="server-side error
>> detected">
>> > + The ivi compositor encountered error while
>> processing a request by this
>> > + application. The error is defined by
>> argument error_code and optional
>> > + error_text.
>> > + If the application requires to associate
>> this error event to a request,
>> > + it can
>> > + 1. send request
>> > + 2. force display roundtrip
>> > + 3. check, if error event was
>> received
>> > + but this restricts the application to
>> have only one open request at a time.
>> > + </description>
>> > + <arg name="error_code" type="int"/>
>> > + <arg name="error_text" type="string"
>> allow-null="true"/>
>> > + </event>
>>
>> Why are you using this rather than the built-in wl_display.error?
>> The built-in wl_display.error also terminates the client when an error
>> is sent. Under what error conditions would you want the client to
>> continue?
>>
>
> Good suggestion!
> According to wayland.xml, error code from 0 to 2 is reserved for global.
> Please teach me there is any manner which number I can use for the above
object? In the feature, if wayland.xml updated to add new global error code
to 3, the local number may need to be incremented.

The wl_display.error event is a bit confusing. The wl_resource_post_error
function takes three arguments. The first argument is an object; the last
two are an error code and a human-readable message string. The error code
should be interpreted relative to the given object. Therefore, you don't
need to worry about colliding with the codes defined in wl_display. If the
error is defined in wl_application you should pass the wl_application
resource into the error event.

One warning about wl_display.error event: all errors are considered fatal
and the client gets automatically disconnected. Given the errors you
listed, this is probably OK. If you want a non-fatal error, you should use
something else And probably not call it "error" (to avoid confusion).

Hope that helps,
--Jason Ekstrand

>
> BR,
> Nobuhiko
>>>
>>> +
>>
>> > + </interface>
>> > +
>> > +</protocol>
>> > --
>> > 1.8.3.1
>> >
>> > _______________________________________________
>> > wayland-devel mailing list
>> > wayland-devel at lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel [1]
>>
>>
>> Links:
>> ------
>> [1] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20140306/eee29eee/attachment-0001.html>
Nobuhiko Tanibata
2014-03-07 07:49:28 UTC
Permalink
2014-03-07 11:37 ? Jason Ekstrand ????????:
> On Mar 6, 2014 7:08 PM, "Nobuhiko Tanibata"
> <nobuhiko_tanibata at xddp.denso.co.jp> wrote:
> >
> > 2014-03-07 00:21 ? Jason Ekstrand ????????:
> >
> >> On Mar 6, 2014 3:53 AM, "Nobuhiko Tanibata"
> >> <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
> >> >
> >> > Add interface ivi_application, which creates ivi_surface objects
> >> tied
> >> > to a given wl_surface with a given id. The given id can be used
> in
> >> a
> >> > shell to identify which application is assigned to a wl_surface
> and
> >> > layout the surface wherever the shell wants. ivi_surface objects
> >> can
> >> > be used to receive status of wl_surface in the scenegraph of the
> >> > compositor.
> >>
> >> In general, I think this looks pretty good. It's nice and simple
> and
> >> only adds what's needed for clients. I do have a couple comments
> >> below.
> >> --Jason Ekstrand
> >>
> >>>
> >> > Signed-off-by: Nobuhiko Tanibata
> >> <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> >> > ---
> >> > protocol/ivi-application.xml | 88
> >> ++++++++++++++++++++++++++++++++++++++++++++
> >> > 1 file changed, 88 insertions(+)
> >> > create mode 100644 protocol/ivi-application.xml
> >> >
> >> > diff --git a/protocol/ivi-application.xml
> >> b/protocol/ivi-application.xml
> >> > new file mode 100644
> >> > index 0000000..e58ad26
> >> > --- /dev/null
> >> > +++ b/protocol/ivi-application.xml
> >> > @@ -0,0 +1,88 @@
> >> > +<?xml version="1.0" encoding="UTF-8"?>
> >> > +<protocol name="ivi_application">
> >> > +
> >> > + <copyright>
> >> > + Copyright (C) 2013 DENSO CORPORATION
> >> > + Copyright (c) 2013 BMW Car IT GmbH
> >> > +
> >> > + Permission is hereby granted, free of charge, to any person
> >> obtaining a copy
> >> > + of this software and associated documentation files (the
> >> "Software"), to deal
> >> > + in the Software without restriction, including without
> >> limitation the rights
> >> > + to use, copy, modify, merge, publish, distribute,
> >> sublicense, and/or sell
> >> > + copies of the Software, and to permit persons to whom the
> >> Software is
> >> > + furnished to do so, subject to the following conditions:
> >> > +
> >> > + The above copyright notice and this permission notice shall
> >> be included in
> >> > + all copies or substantial portions of the Software.
> >> > +
> >> > + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> >> KIND, EXPRESS OR
> >> > + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> >> MERCHANTABILITY,
> >> > + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
> >> EVENT SHALL THE
> >> > + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> >> DAMAGES OR OTHER
> >> > + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> >> OTHERWISE, ARISING FROM,
> >> > + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> >> OTHER DEALINGS IN
> >> > + THE SOFTWARE.
> >> > + </copyright>
> >> > +
> >> > + <interface name="ivi_surface" version="1">
> >> > + <description summary="application interface to surface
> >> in ivi compositor"/>
> >> > +
> >> > + <request name="destroy" type="destructor">
> >> > + <description summary="destroy ivi_surface"/>
> >> > + </request>
> >> > +
> >> > + <event name="visibility">
> >> > + <description summary="visibility of surface in
> >> ivi compositor has changed">
> >> > + The new visibility state is provided in
> >> argument visibility.
> >> > + If visibility is 0, the surface has become
> >> invisible.
> >> > + If visibility is not 0, the surface has
> >> become visible.
> >> > + </description>
> >> > + <arg name="visibility" type="int"/>
> >> > + </event>
> >> > +
> >> > + </interface>
> >> > +
> >> > + <interface name="ivi_application" version="1">
> >> > + <description summary="interface for ivi applications
> >> to use ivi compositor features"/>
> >> > +
> >> > + <request name="surface_create">
> >> > + <description summary="create surface in ivi
> >> compositor">
> >> > + surface_create will create a new surface
> >> with surface_id in ivi compositor,
> >> > + if it does not yet exists. If the surface
> >> with surface_id already exists in
> >> > + ivi compositor, the application content
> >> provided in argument surface will
> >> > + be used as surface content. If an other
> >> ivi application already registered
> >> > + content for surface with surface_id, an
> >> error event will indicate the problem.
> >> > + </description>
> >> > + <arg name="id_surface" type="uint"/>
> >> > + <arg name="surface" type="object"
> >> interface="wl_surface"/>
> >> > + <arg name="id" type="new_id"
> >> interface="ivi_surface"/>
> >> > + </request>
> >> > +
> >> > + <enum name="error_code">
> >> > + <description summary="possible error codes
> >> returned by ivi compositor">
> >> > + These error codes define all possible
> >> error codes returned by ivi compositor
> >> > + on server-side errors.
> >> > + </description>
> >> > + <entry name="unknown_error" value="1"
> >> summary="unknown error encountered"/>
> >>
> >> What kinds of things do you use "unknown error" for? I'm not sure
> >> how that's useful to the client.
> >>
> >
> > Hi Jason,
> >
> > Thank you for reviewing.
> >
> > I see. From this review point, it shall not return no useful value
> to the client.
> > I break down more here.
> > - id in use: specified ID for ivi_surface is already used by itself
> or other client.
> > - resource in use: specified ID of wl_surface is already tie to
> another ID of ivi_surface.
> > - invalid resource: specified ID of wl_surface is not valid in
> server.
> >
> > I think these three is sufficient for client.
> >
> >
> >>> + <entry name="resource_in_use" value="2"
> >>
> >> summary="resource is in use and can not be shared"/>
> >>
> >> What kind of resource does this refer to? It looks like you use it
> >> if someone tries to call surface_create twice on the same surface,
> but
> >> you don't specify.
> >>
> >>> + </enum>
> >>
> >> > +
> >> > + <event name="error">
> >> > + <description summary="server-side error
> >> detected">
> >> > + The ivi compositor encountered error while
> >> processing a request by this
> >> > + application. The error is defined by
> >> argument error_code and optional
> >> > + error_text.
> >> > + If the application requires to associate
> >> this error event to a request,
> >> > + it can
> >> > + 1. send request
> >> > + 2. force display roundtrip
> >> > + 3. check, if error event was
> >> received
> >> > + but this restricts the application to
> >> have only one open request at a time.
> >> > + </description>
> >> > + <arg name="error_code" type="int"/>
> >> > + <arg name="error_text" type="string"
> >> allow-null="true"/>
> >> > + </event>
> >>
> >> Why are you using this rather than the built-in wl_display.error?
> >> The built-in wl_display.error also terminates the client when an
> error
> >> is sent. Under what error conditions would you want the client to
> >> continue?
> >>
> >
> > Good suggestion!
> > According to wayland.xml, error code from 0 to 2 is reserved for
> global.
> > Please teach me there is any manner which number I can use for the
> above object? In the feature, if wayland.xml updated to add new global
> error code to 3, the local number may need to be incremented.
>
> The wl_display.error event is a bit confusing. The
> wl_resource_post_error function takes three arguments. The first
> argument is an object; the last two are an error code and a
> human-readable message string. The error code should be interpreted
> relative to the given object. Therefore, you don't need to worry about
> colliding with the codes defined in wl_display. If the error is
> defined in wl_application you should pass the wl_application resource
> into the error event.
>
> One warning about wl_display.error event: all errors are considered
> fatal and the client gets automatically disconnected. Given the errors
> you listed, this is probably OK. If you want a non-fatal error, you

I see. Thank you. In its usecase, a ivi_application will create several
ivi_surfaces. If it is disconnected, all ivi_surfaces are destroyed and
it will not fit the use case.

So I will consider it to be changed to naming "warning" as event in V2.

Thanks,
Nobuhiko

> should use something else And probably not call it "error" (to avoid
> confusion).
>
> Hope that helps,
> --Jason Ekstrand
>
>>
> > BR,
> > Nobuhiko
> >>>
> >>> +
> >>
> >> > + </interface>
> >> > +
> >> > +</protocol>
> >> > --
> >> > 1.8.3.1
> >> >
> >> > _______________________________________________
> >> > wayland-devel mailing list
> >> > wayland-devel at lists.freedesktop.org
> >> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel [1]
> [1]
> >>
> >>
> >> Links:
> >> ------
> >> [1] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> [1]
>
>
> Links:
> ------
> [1] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
Nobuhiko Tanibata
2014-03-07 13:56:02 UTC
Permalink
Add interface ivi_application, which creates ivi_surface objects tied
to a given wl_surface with a given id. The given id can be used in a
shell to identify which application is assigned to a wl_surface and
layout the surface wherever the shell wants. ivi_surface objects can
be used to receive status of wl_surface in the scenegraph of the
compositor.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- Rename "error" to "warning" because meaning of "error" in wayland is fatal.

protocol/ivi-application.xml | 88 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100755 protocol/ivi-application.xml

diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
new file mode 100755
index 0000000..8659ec6
--- /dev/null
+++ b/protocol/ivi-application.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ivi_application">
+
+ <copyright>
+ Copyright (C) 2013 DENSO CORPORATION
+ Copyright (c) 2013 BMW Car IT GmbH
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ </copyright>
+
+ <interface name="ivi_surface" version="1">
+ <description summary="application interface to surface in ivi compositor"/>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy ivi_surface"/>
+ </request>
+
+ <event name="visibility">
+ <description summary="visibility of surface in ivi compositor has changed">
+ The new visibility state is provided in argument visibility.
+ If visibility is 0, the surface has become invisible.
+ If visibility is not 0, the surface has become visible.
+ </description>
+ <arg name="visibility" type="int"/>
+ </event>
+
+ </interface>
+
+ <interface name="ivi_application" version="1">
+ <description summary="interface for ivi applications to use ivi compositor features"/>
+
+ <request name="surface_create">
+ <description summary="create surface in ivi compositor">
+ surface_create will create a new surface with surface_id in ivi compositor,
+ if it does not yet exists. If the surface with surface_id already exists in
+ ivi compositor, the application content provided in argument surface will
+ be used as surface content. If an other ivi application already registered
+ content for surface with surface_id, an warning event will indicate the problem.
+ </description>
+ <arg name="id_surface" type="uint"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="id" type="new_id" interface="ivi_surface"/>
+ </request>
+
+ <enum name="warning_code">
+ <description summary="possible warning codes returned by ivi compositor">
+ These warning codes define all possible warning codes returned by ivi compositor
+ on server-side warnings.
+ </description>
+ <entry name="invalid_wl_surface" value="1" summary="wl_surface is invalid"/>
+ <entry name="surface_id_in_use" value="2" summary="surface_id is in use and can not be shared"/>
+ </enum>
+
+ <event name="warning">
+ <description summary="server-side warning detected">
+ The ivi compositor encountered warning while processing a request by this
+ application. The warning is defined by argument warning_code and optional
+ warning_text.
+ If the application requires to associate this warning event to a request,
+ it can
+ 1. send request
+ 2. force display roundtrip
+ 3. check, if warning event was received
+ but this restricts the application to have only one open request at a time.
+ </description>
+ <arg name="warning_code" type="int"/>
+ <arg name="warning_text" type="string" allow-null="true"/>
+ </event>
+
+ </interface>
+
+</protocol>
--
1.8.3.1
Jason Ekstrand
2014-03-07 16:39:44 UTC
Permalink
On Mar 7, 2014 7:56 AM, "Nobuhiko Tanibata" <
NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>
> Add interface ivi_application, which creates ivi_surface objects tied
> to a given wl_surface with a given id. The given id can be used in a
> shell to identify which application is assigned to a wl_surface and
> layout the surface wherever the shell wants. ivi_surface objects can
> be used to receive status of wl_surface in the scenegraph of the
> compositor.
>
> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> ---
>
> Changes for v2:
> - Rename "error" to "warning" because meaning of "error" in wayland is
fatal.
>
> protocol/ivi-application.xml | 88
++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 88 insertions(+)
> create mode 100755 protocol/ivi-application.xml
>
> diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
> new file mode 100755
> index 0000000..8659ec6
> --- /dev/null
> +++ b/protocol/ivi-application.xml
> @@ -0,0 +1,88 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<protocol name="ivi_application">
> +
> + <copyright>
> + Copyright (C) 2013 DENSO CORPORATION
> + Copyright (c) 2013 BMW Car IT GmbH
> +
> + Permission is hereby granted, free of charge, to any person
obtaining a copy
> + of this software and associated documentation files (the
"Software"), to deal
> + in the Software without restriction, including without limitation
the rights
> + to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
> + copies of the Software, and to permit persons to whom the Software is
> + furnished to do so, subject to the following conditions:
> +
> + The above copyright notice and this permission notice shall be
included in
> + all copies or substantial portions of the Software.
> +
> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
> + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
> + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
> + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
> + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
> + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
> + THE SOFTWARE.
> + </copyright>
> +
> + <interface name="ivi_surface" version="1">
> + <description summary="application interface to surface in ivi
compositor"/>
> +
> + <request name="destroy" type="destructor">
> + <description summary="destroy ivi_surface"/>
> + </request>
> +
> + <event name="visibility">
> + <description summary="visibility of surface in ivi
compositor has changed">
> + The new visibility state is provided in argument
visibility.
> + If visibility is 0, the surface has become invisible.
> + If visibility is not 0, the surface has become visible.
> + </description>
> + <arg name="visibility" type="int"/>
> + </event>
> +
> + </interface>
> +
> + <interface name="ivi_application" version="1">
> + <description summary="interface for ivi applications to use ivi
compositor features"/>
> +
> + <request name="surface_create">
> + <description summary="create surface in ivi compositor">
> + surface_create will create a new surface with surface_id
in ivi compositor,
> + if it does not yet exists. If the surface with
surface_id already exists in
> + ivi compositor, the application content provided in
argument surface will
> + be used as surface content. If an other ivi application
already registered
> + content for surface with surface_id, an warning event
will indicate the problem.
> + </description>
> + <arg name="id_surface" type="uint"/>
> + <arg name="surface" type="object" interface="wl_surface"/>
> + <arg name="id" type="new_id" interface="ivi_surface"/>
> + </request>
> +
> + <enum name="warning_code">
> + <description summary="possible warning codes returned by ivi
compositor">
> + These warning codes define all possible warning codes
returned by ivi compositor
> + on server-side warnings.
> + </description>
> + <entry name="invalid_wl_surface" value="1"
summary="wl_surface is invalid"/>
> + <entry name="surface_id_in_use" value="2"
summary="surface_id is in use and can not be shared"/>
> + </enum>

I have a couple more thoughts about these errors/warnings. For one, I
think some of these should be errors. For instance, there is no way that
the given wl_surface will be invalid unless the client has destroyed it.
Honestly, I'm not even sure if it's possible, given how libwayland is
written, to get a truely invalid wl_surface. From what you've written in
previous e-mails, I can't quite tell but it sounds like you want to prevent
a client from attaaching multiple ivi_surface objects (and IVI ID's) to the
same surface. If this is the case then doing so should probably also be a
fatal error because that means the client was written wrong.

With regards to what happens if a client tries to use an ID that's already
in use, I'm not 100% sure what to do there. You know IVI systems better
than I do. Is this something that happens with some degree of regularity?
Or is this something that only happens if the there is a mistake in the
client code? I'll leave that up to you.

That said, if there is an issue, you need to explicitly say what happens to
the newly created ivi_surface object. The Wayland protocol has no concept
of returning NULL. Whenever a request or event is fired which has a new_id
parameter, both client and server-side objects always get created. If
surface_create can throw a non-fatal error, we need to decide what happens
to the new ivi_surface object. One way to do this would be to have the
error/warning event on the ivi_surface itself instead of on
ivi_application. Then the client would know that if it recieves the
error/warning, that it needs to destroy the corresponding ivi_surface.
Otherwise, like you note below, they have to roundtrip after every call to
ivi_application.surface_create.

Thanks,
--Jason Ekstrand

> +
> + <event name="warning">
> + <description summary="server-side warning detected">
> + The ivi compositor encountered warning while processing
a request by this
> + application. The warning is defined by argument
warning_code and optional
> + warning_text.
> + If the application requires to associate this warning
event to a request,
> + it can
> + 1. send request
> + 2. force display roundtrip
> + 3. check, if warning event was received
> + but this restricts the application to have only one
open request at a time.
> + </description>
> + <arg name="warning_code" type="int"/>
> + <arg name="warning_text" type="string" allow-null="true"/>
> + </event>
> +
> + </interface>
> +
> +</protocol>
> --
> 1.8.3.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20140307/5aae03b2/attachment-0001.html>
Pekka Paalanen
2014-03-10 08:41:38 UTC
Permalink
On Fri, 7 Mar 2014 10:39:44 -0600
Jason Ekstrand <jason at jlekstrand.net> wrote:

> On Mar 7, 2014 7:56 AM, "Nobuhiko Tanibata" <
> NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
> >
> > Add interface ivi_application, which creates ivi_surface objects
> > tied to a given wl_surface with a given id. The given id can be
> > used in a shell to identify which application is assigned to a
> > wl_surface and layout the surface wherever the shell wants.
> > ivi_surface objects can be used to receive status of wl_surface in
> > the scenegraph of the compositor.
> >
> > Signed-off-by: Nobuhiko Tanibata
> > <NOBUHIKO_TANIBATA at xddp.denso.co.jp> ---
> >
> > Changes for v2:
> > - Rename "error" to "warning" because meaning of "error" in
> > wayland is
> fatal.
> >
> > protocol/ivi-application.xml | 88
> ++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 88 insertions(+)
> > create mode 100755 protocol/ivi-application.xml
> >
> > diff --git a/protocol/ivi-application.xml
> > b/protocol/ivi-application.xml new file mode 100755
> > index 0000000..8659ec6
> > --- /dev/null
> > +++ b/protocol/ivi-application.xml
> > @@ -0,0 +1,88 @@
> > +<?xml version="1.0" encoding="UTF-8"?>
> > +<protocol name="ivi_application">
> > +
> > + <copyright>
> > + Copyright (C) 2013 DENSO CORPORATION
> > + Copyright (c) 2013 BMW Car IT GmbH
> > +
> > + Permission is hereby granted, free of charge, to any person
> obtaining a copy
> > + of this software and associated documentation files (the
> "Software"), to deal
> > + in the Software without restriction, including without
> > limitation
> the rights
> > + to use, copy, modify, merge, publish, distribute, sublicense,
> > and/or
> sell
> > + copies of the Software, and to permit persons to whom the
> > Software is
> > + furnished to do so, subject to the following conditions:
> > +
> > + The above copyright notice and this permission notice shall be
> included in
> > + all copies or substantial portions of the Software.
> > +
> > + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> > + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> > + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
> > EVENT
> SHALL THE
> > + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
> > OR
> OTHER
> > + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> ARISING FROM,
> > + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS IN
> > + THE SOFTWARE.
> > + </copyright>
> > +
> > + <interface name="ivi_surface" version="1">
> > + <description summary="application interface to surface in
> > ivi
> compositor"/>
> > +
> > + <request name="destroy" type="destructor">
> > + <description summary="destroy ivi_surface"/>
> > + </request>
> > +
> > + <event name="visibility">
> > + <description summary="visibility of surface in ivi
> compositor has changed">
> > + The new visibility state is provided in argument
> visibility.
> > + If visibility is 0, the surface has become
> > invisible.
> > + If visibility is not 0, the surface has become
> > visible.
> > + </description>
> > + <arg name="visibility" type="int"/>
> > + </event>
> > +
> > + </interface>
> > +
> > + <interface name="ivi_application" version="1">
> > + <description summary="interface for ivi applications to
> > use ivi
> compositor features"/>
> > +
> > + <request name="surface_create">
> > + <description summary="create surface in ivi
> > compositor">
> > + surface_create will create a new surface with
> > surface_id
> in ivi compositor,
> > + if it does not yet exists. If the surface with
> surface_id already exists in
> > + ivi compositor, the application content provided in
> argument surface will
> > + be used as surface content. If an other ivi
> > application
> already registered
> > + content for surface with surface_id, an warning
> > event
> will indicate the problem.
> > + </description>
> > + <arg name="id_surface" type="uint"/>
> > + <arg name="surface" type="object"
> > interface="wl_surface"/>
> > + <arg name="id" type="new_id" interface="ivi_surface"/>
> > + </request>
> > +
> > + <enum name="warning_code">
> > + <description summary="possible warning codes returned
> > by ivi
> compositor">
> > + These warning codes define all possible warning
> > codes
> returned by ivi compositor
> > + on server-side warnings.
> > + </description>
> > + <entry name="invalid_wl_surface" value="1"
> summary="wl_surface is invalid"/>
> > + <entry name="surface_id_in_use" value="2"
> summary="surface_id is in use and can not be shared"/>
> > + </enum>
>
> I have a couple more thoughts about these errors/warnings. For one, I
> think some of these should be errors. For instance, there is no way
> that the given wl_surface will be invalid unless the client has
> destroyed it. Honestly, I'm not even sure if it's possible, given how
> libwayland is written, to get a truely invalid wl_surface. From what
> you've written in previous e-mails, I can't quite tell but it sounds
> like you want to prevent a client from attaaching multiple
> ivi_surface objects (and IVI ID's) to the same surface. If this is
> the case then doing so should probably also be a fatal error because
> that means the client was written wrong.
>
> With regards to what happens if a client tries to use an ID that's
> already in use, I'm not 100% sure what to do there. You know IVI
> systems better than I do. Is this something that happens with some
> degree of regularity? Or is this something that only happens if the
> there is a mistake in the client code? I'll leave that up to you.
>
> That said, if there is an issue, you need to explicitly say what
> happens to the newly created ivi_surface object. The Wayland
> protocol has no concept of returning NULL. Whenever a request or
> event is fired which has a new_id parameter, both client and
> server-side objects always get created. If surface_create can throw
> a non-fatal error, we need to decide what happens to the new
> ivi_surface object. One way to do this would be to have the
> error/warning event on the ivi_surface itself instead of on
> ivi_application. Then the client would know that if it recieves the
> error/warning, that it needs to destroy the corresponding
> ivi_surface. Otherwise, like you note below, they have to roundtrip
> after every call to ivi_application.surface_create.

Hi Nobuhiko,

Jason pretty much covered everything that came to my mind, too.

I just want to stress, that if a problem is caused by e.g. bad
IVI-system configuration done by the system manufacturer rather than
something the end user did, then I think you should keep to fatal
errors. If a car manufacturer or a software vendor configures or codes
something wrong, you really want to catch all those errors ASAP.
Killing the whole client is a good way to point out such error
conditions that really should never happen at runtime. Conflicting
surface ID thing sounds like it is the system maker's fault, not an end
user mistake.

OTOH, if these problem cases can happen when the end user does
something wrong, e.g. tries to open an application twice or whatever,
the first thing would be to make sure the UI prevents such things from
occurring in the first place. If you still need non-fatal errors in the
protocol, then you have to have a solid plan on what happens with the
request that caused it. Jason explained it well, you have to define how
the already created protocol object works after the error has occurred
in the compositor, i.e. even before the client receives the error
event. The client might send requests to or requests referring the
failed object before it processes the error event. You also should say
something about how the client is expected to recover from this error.
If the client is not disconnected, there must be a way to recover
smoothly.

Jason's point about avoiding the roundtrip is a very good one.

I haven't read the rest of the patches yet, but if you have error
events defined in other protocol parts, the same comments apply.

Personally I would hope for some more explanations on what the "ID" is,
and how it is used, or at least a pointer in the .xml to more extensive
documentation. It is quite odd to see numeric IDs passed manually in
Wayland protocol.


Thanks,
pq

> > +
> > + <event name="warning">
> > + <description summary="server-side warning detected">
> > + The ivi compositor encountered warning while
> > processing
> a request by this
> > + application. The warning is defined by argument
> warning_code and optional
> > + warning_text.
> > + If the application requires to associate this
> > warning
> event to a request,
> > + it can
> > + 1. send request
> > + 2. force display roundtrip
> > + 3. check, if warning event was received
> > + but this restricts the application to have only
> > one
> open request at a time.
> > + </description>
> > + <arg name="warning_code" type="int"/>
> > + <arg name="warning_text" type="string"
> > allow-null="true"/>
> > + </event>
> > +
> > + </interface>
> > +
> > +</protocol>
> > --
> > 1.8.3.1
> >
> > _______________________________________________
> > wayland-devel mailing list
> > wayland-devel at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel
Nobuhiko Tanibata
2014-03-10 10:26:10 UTC
Permalink
2014-03-10 17:41 ? Pekka Paalanen ????????:
> On Fri, 7 Mar 2014 10:39:44 -0600
> Jason Ekstrand <jason at jlekstrand.net> wrote:
>
>> On Mar 7, 2014 7:56 AM, "Nobuhiko Tanibata" <
>> NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>> >
>> > Add interface ivi_application, which creates ivi_surface objects
>> > tied to a given wl_surface with a given id. The given id can be
>> > used in a shell to identify which application is assigned to a
>> > wl_surface and layout the surface wherever the shell wants.
>> > ivi_surface objects can be used to receive status of wl_surface in
>> > the scenegraph of the compositor.
>> >
>> > Signed-off-by: Nobuhiko Tanibata
>> > <NOBUHIKO_TANIBATA at xddp.denso.co.jp> ---
>> >
>> > Changes for v2:
>> > - Rename "error" to "warning" because meaning of "error" in
>> > wayland is
>> fatal.
>> >
>> > protocol/ivi-application.xml | 88
>> ++++++++++++++++++++++++++++++++++++++++++++
>> > 1 file changed, 88 insertions(+)
>> > create mode 100755 protocol/ivi-application.xml
>> >
>> > diff --git a/protocol/ivi-application.xml
>> > b/protocol/ivi-application.xml new file mode 100755
>> > index 0000000..8659ec6
>> > --- /dev/null
>> > +++ b/protocol/ivi-application.xml
>> > @@ -0,0 +1,88 @@
>> > +<?xml version="1.0" encoding="UTF-8"?>
>> > +<protocol name="ivi_application">
>> > +
>> > + <copyright>
>> > + Copyright (C) 2013 DENSO CORPORATION
>> > + Copyright (c) 2013 BMW Car IT GmbH
>> > +
>> > + Permission is hereby granted, free of charge, to any person
>> obtaining a copy
>> > + of this software and associated documentation files (the
>> "Software"), to deal
>> > + in the Software without restriction, including without
>> > limitation
>> the rights
>> > + to use, copy, modify, merge, publish, distribute, sublicense,
>> > and/or
>> sell
>> > + copies of the Software, and to permit persons to whom the
>> > Software is
>> > + furnished to do so, subject to the following conditions:
>> > +
>> > + The above copyright notice and this permission notice shall be
>> included in
>> > + all copies or substantial portions of the Software.
>> > +
>> > + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> > + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> > + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
>> > EVENT
>> SHALL THE
>> > + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
>> > OR
>> OTHER
>> > + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> > + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> DEALINGS IN
>> > + THE SOFTWARE.
>> > + </copyright>
>> > +
>> > + <interface name="ivi_surface" version="1">
>> > + <description summary="application interface to surface in
>> > ivi
>> compositor"/>
>> > +
>> > + <request name="destroy" type="destructor">
>> > + <description summary="destroy ivi_surface"/>
>> > + </request>
>> > +
>> > + <event name="visibility">
>> > + <description summary="visibility of surface in ivi
>> compositor has changed">
>> > + The new visibility state is provided in argument
>> visibility.
>> > + If visibility is 0, the surface has become
>> > invisible.
>> > + If visibility is not 0, the surface has become
>> > visible.
>> > + </description>
>> > + <arg name="visibility" type="int"/>
>> > + </event>
>> > +
>> > + </interface>
>> > +
>> > + <interface name="ivi_application" version="1">
>> > + <description summary="interface for ivi applications to
>> > use ivi
>> compositor features"/>
>> > +
>> > + <request name="surface_create">
>> > + <description summary="create surface in ivi
>> > compositor">
>> > + surface_create will create a new surface with
>> > surface_id
>> in ivi compositor,
>> > + if it does not yet exists. If the surface with
>> surface_id already exists in
>> > + ivi compositor, the application content provided in
>> argument surface will
>> > + be used as surface content. If an other ivi
>> > application
>> already registered
>> > + content for surface with surface_id, an warning
>> > event
>> will indicate the problem.
>> > + </description>
>> > + <arg name="id_surface" type="uint"/>
>> > + <arg name="surface" type="object"
>> > interface="wl_surface"/>
>> > + <arg name="id" type="new_id" interface="ivi_surface"/>
>> > + </request>
>> > +
>> > + <enum name="warning_code">
>> > + <description summary="possible warning codes returned
>> > by ivi
>> compositor">
>> > + These warning codes define all possible warning
>> > codes
>> returned by ivi compositor
>> > + on server-side warnings.
>> > + </description>
>> > + <entry name="invalid_wl_surface" value="1"
>> summary="wl_surface is invalid"/>
>> > + <entry name="surface_id_in_use" value="2"
>> summary="surface_id is in use and can not be shared"/>
>> > + </enum>
>>
>> I have a couple more thoughts about these errors/warnings. For one, I
>> think some of these should be errors. For instance, there is no way
>> that the given wl_surface will be invalid unless the client has
>> destroyed it. Honestly, I'm not even sure if it's possible, given how
>> libwayland is written, to get a truely invalid wl_surface. From what
>> you've written in previous e-mails, I can't quite tell but it sounds
>> like you want to prevent a client from attaaching multiple
>> ivi_surface objects (and IVI ID's) to the same surface. If this is
>> the case then doing so should probably also be a fatal error because
>> that means the client was written wrong.
>>
>> With regards to what happens if a client tries to use an ID that's
>> already in use, I'm not 100% sure what to do there. You know IVI
>> systems better than I do. Is this something that happens with some
>> degree of regularity? Or is this something that only happens if the
>> there is a mistake in the client code? I'll leave that up to you.
>>

Hi Jason and pq,

- invalid_wl_surface
In the automotive use case, the worst case may need to be taken account.
In this use case, One application, e.g. Car navigation, will create
several ivi_surfaces in one process, its means one connection. These
surfaces for Map, traffic info, corner view, and so on. If it is
disconnected when something happen on creation of only ivi_surface, All
surfaces of car navigation will not work. Ideally, we shall remove all
bugs and release well-tested application to prevent it. However its
application required to work partially as fault tolerant. That's way, I
propose it as warnings and it is really fatal to the system, the Car
navigation application will notify it to the central controller to
decide whether the Car navigation application shall be restarted or not.

>> That said, if there is an issue, you need to explicitly say what
>> happens to the newly created ivi_surface object. The Wayland
>> protocol has no concept of returning NULL. Whenever a request or
>> event is fired which has a new_id parameter, both client and
>> server-side objects always get created. If surface_create can throw
>> a non-fatal error, we need to decide what happens to the new
>> ivi_surface object. One way to do this would be to have the
>> error/warning event on the ivi_surface itself instead of on
>> ivi_application. Then the client would know that if it recieves the
>> error/warning, that it needs to destroy the corresponding
>> ivi_surface. Otherwise, like you note below, they have to roundtrip
>> after every call to ivi_application.surface_create.
>

In case of that I have to do it, I will follow your suggested way. Thank
you for good ideas.

> Hi Nobuhiko,
>
> Jason pretty much covered everything that came to my mind, too.
>
> I just want to stress, that if a problem is caused by e.g. bad
> IVI-system configuration done by the system manufacturer rather than
> something the end user did, then I think you should keep to fatal
> errors. If a car manufacturer or a software vendor configures or codes
> something wrong, you really want to catch all those errors ASAP.
> Killing the whole client is a good way to point out such error
> conditions that really should never happen at runtime. Conflicting
> surface ID thing sounds like it is the system maker's fault, not an end
> user mistake.
>

Thank you for comment as well. As I mention it in the above, I want to
suggest the above mentioned use case.

> OTOH, if these problem cases can happen when the end user does
> something wrong, e.g. tries to open an application twice or whatever,
> the first thing would be to make sure the UI prevents such things from
> occurring in the first place.
I agree with you. UI shall prevent it.

> If you still need non-fatal errors in the
> protocol, then you have to have a solid plan on what happens with the
> request that caused it. Jason explained it well, you have to define how
> the already created protocol object works after the error has occurred
> in the compositor, i.e. even before the client receives the error
> event. The client might send requests to or requests referring the
> failed object before it processes the error event. You also should say
> something about how the client is expected to recover from this error.
> If the client is not disconnected, there must be a way to recover
> smoothly.
>

Yes, you are right. I will add clear comment in ivi_application.xml to
say how to
follow such a error.

> Jason's point about avoiding the roundtrip is a very good one.
>
> I haven't read the rest of the patches yet, but if you have error
> events defined in other protocol parts, the same comments apply.
>
> Personally I would hope for some more explanations on what the "ID" is,
> and how it is used, or at least a pointer in the .xml to more extensive
> documentation. It is quite odd to see numeric IDs passed manually in
> Wayland protocol.
>

Traditionally, automotive system list up all applications which will be
installed to the application with numeric IDs. The text might be OK to
manage them. Additionally, in the future, certified download
applications are also manged by IDs. This might be easier way then using
just a text. I will add such description to protocol summary.

Thank you,
Nobuhiko

>
> Thanks,
> pq
>
>> > +
>> > + <event name="warning">
>> > + <description summary="server-side warning detected">
>> > + The ivi compositor encountered warning while
>> > processing
>> a request by this
>> > + application. The warning is defined by argument
>> warning_code and optional
>> > + warning_text.
>> > + If the application requires to associate this
>> > warning
>> event to a request,
>> > + it can
>> > + 1. send request
>> > + 2. force display roundtrip
>> > + 3. check, if warning event was received
>> > + but this restricts the application to have only
>> > one
>> open request at a time.
>> > + </description>
>> > + <arg name="warning_code" type="int"/>
>> > + <arg name="warning_text" type="string"
>> > allow-null="true"/>
>> > + </event>
>> > +
>> > + </interface>
>> > +
>> > +</protocol>
>> > --
>> > 1.8.3.1
>> >
>> > _______________________________________________
>> > wayland-devel mailing list
>> > wayland-devel at lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
Pekka Paalanen
2014-03-10 13:01:47 UTC
Permalink
On Fri, 7 Mar 2014 22:56:02 +0900
Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:

> Add interface ivi_application, which creates ivi_surface objects tied
> to a given wl_surface with a given id. The given id can be used in a
> shell to identify which application is assigned to a wl_surface and
> layout the surface wherever the shell wants. ivi_surface objects can
> be used to receive status of wl_surface in the scenegraph of the
> compositor.
>
> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> ---
>
> Changes for v2:
> - Rename "error" to "warning" because meaning of "error" in wayland is fatal.
>
> protocol/ivi-application.xml | 88 ++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 88 insertions(+)
> create mode 100755 protocol/ivi-application.xml
>
> diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
> new file mode 100755
> index 0000000..8659ec6
> --- /dev/null
> +++ b/protocol/ivi-application.xml
> @@ -0,0 +1,88 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<protocol name="ivi_application">
> +
> + <copyright>
> + Copyright (C) 2013 DENSO CORPORATION
> + Copyright (c) 2013 BMW Car IT GmbH
> +
> + Permission is hereby granted, free of charge, to any person obtaining a copy
> + of this software and associated documentation files (the "Software"), to deal
> + in the Software without restriction, including without limitation the rights
> + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + copies of the Software, and to permit persons to whom the Software is
> + furnished to do so, subject to the following conditions:
> +
> + The above copyright notice and this permission notice shall be included in
> + all copies or substantial portions of the Software.
> +
> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + THE SOFTWARE.
> + </copyright>
> +
> + <interface name="ivi_surface" version="1">
> + <description summary="application interface to surface in ivi compositor"/>

Hi,

one more thing that came to my mind: you need to define what happens
when the wl_surface, that was given to ivi_application.surface_create
to create this ivi_surface, gets destroyed while the ivi_surface still
exists.


Thanks,
pq

> +
> + <request name="destroy" type="destructor">
> + <description summary="destroy ivi_surface"/>
> + </request>
> +
> + <event name="visibility">
> + <description summary="visibility of surface in ivi compositor has changed">
> + The new visibility state is provided in argument visibility.
> + If visibility is 0, the surface has become invisible.
> + If visibility is not 0, the surface has become visible.
> + </description>
> + <arg name="visibility" type="int"/>
> + </event>
> +
> + </interface>
> +
> + <interface name="ivi_application" version="1">
> + <description summary="interface for ivi applications to use ivi compositor features"/>
> +
> + <request name="surface_create">
> + <description summary="create surface in ivi compositor">
> + surface_create will create a new surface with surface_id in ivi compositor,
> + if it does not yet exists. If the surface with surface_id already exists in
> + ivi compositor, the application content provided in argument surface will
> + be used as surface content. If an other ivi application already registered
> + content for surface with surface_id, an warning event will indicate the problem.
> + </description>
> + <arg name="id_surface" type="uint"/>
> + <arg name="surface" type="object" interface="wl_surface"/>
> + <arg name="id" type="new_id" interface="ivi_surface"/>
> + </request>
> +
> + <enum name="warning_code">
> + <description summary="possible warning codes returned by ivi compositor">
> + These warning codes define all possible warning codes returned by ivi compositor
> + on server-side warnings.
> + </description>
> + <entry name="invalid_wl_surface" value="1" summary="wl_surface is invalid"/>
> + <entry name="surface_id_in_use" value="2" summary="surface_id is in use and can not be shared"/>
> + </enum>
> +
> + <event name="warning">
> + <description summary="server-side warning detected">
> + The ivi compositor encountered warning while processing a request by this
> + application. The warning is defined by argument warning_code and optional
> + warning_text.
> + If the application requires to associate this warning event to a request,
> + it can
> + 1. send request
> + 2. force display roundtrip
> + 3. check, if warning event was received
> + but this restricts the application to have only one open request at a time.
> + </description>
> + <arg name="warning_code" type="int"/>
> + <arg name="warning_text" type="string" allow-null="true"/>
> + </event>
> +
> + </interface>
> +
> +</protocol>
Nobuhiko Tanibata
2014-03-12 15:03:21 UTC
Permalink
Add interface ivi_application, which creates ivi_surface objects tied
to a given wl_surface with a given id. The given id can be used in a
shell to identify which application is assigned to a wl_surface and
layout the surface wherever the shell wants. ivi_surface objects can
be used to receive status of wl_surface in the scenegraph of the
compositor.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- Rename "error" to "warning" because meaning of "error" in wayland is fatal.

Changes for v3:
- Move "warning" from ivi_application to ivi_surface.
- Squash Makefile.
- Add description to ivi_surface:destroy.
- Update description of ivi_application:surface_create.

protocol/Makefile.am | 3 +-
protocol/ivi-application.xml | 96 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 1 deletion(-)
create mode 100644 protocol/ivi-application.xml

diff --git a/protocol/Makefile.am b/protocol/Makefile.am
index 5e331a7..9913f16 100644
--- a/protocol/Makefile.am
+++ b/protocol/Makefile.am
@@ -8,7 +8,8 @@ protocol_sources = \
text-cursor-position.xml \
wayland-test.xml \
xdg-shell.xml \
- scaler.xml
+ scaler.xml \
+ ivi-application.xml

if HAVE_XMLLINT
.PHONY: validate
diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
new file mode 100644
index 0000000..8f5c23d
--- /dev/null
+++ b/protocol/ivi-application.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ivi_application">
+
+ <copyright>
+ Copyright (C) 2013 DENSO CORPORATION
+ Copyright (c) 2013 BMW Car IT GmbH
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ </copyright>
+
+ <interface name="ivi_surface" version="1">
+ <description summary="application interface to surface in ivi compositor"/>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy ivi_surface">
+ This removes link from surface_id to wl_surface. However it doesn't
+ remove internal properties, e.g. position, visibility, and so on, which
+ is set to the surface_id. This means when some issues happen on clients
+ and a ivi_surface is destroyed, it can use previous properties immediately
+ without setting it again if it restarts and attaches new wl_surface to
+ the same surface_id.
+ </description>
+ </request>
+
+ <event name="visibility">
+ <description summary="visibility of surface in ivi compositor has changed">
+ The new visibility state is provided in argument visibility.
+ If visibility is 0, the surface has become invisible.
+ If visibility is not 0, the surface has become visible.
+ </description>
+ <arg name="visibility" type="int"/>
+ </event>
+
+ <enum name="warning_code">
+ <description summary="possible warning codes returned by ivi compositor">
+ These warning codes define all possible warning codes returned by ivi compositor
+ on server-side warnings.
+ invalid_wl_surface: invalid wl_surface is set. This happen if wl_surface is destroy before this.
+ surface_id_in_use: surface_id is already assigned by another application.
+ </description>
+ <entry name="invalid_wl_surface" value="1" summary="wl_surface is invalid"/>
+ <entry name="surface_id_in_use" value="2" summary="surface_id is in use and can not be shared"/>
+ </enum>
+
+ <event name="warning">
+ <description summary="server-side warning detected">
+ The ivi compositor encountered warning while processing a request by this
+ application. The warning is defined by argument warning_code and optional
+ warning_text. If the warning is detected, client shall destroy the ivi_surface
+ object.
+ </description>
+ <arg name="warning_code" type="int"/>
+ <arg name="warning_text" type="string" allow-null="true"/>
+ </event>
+
+ </interface>
+
+ <interface name="ivi_application" version="1">
+ <description summary="interface for ivi applications to use ivi compositor features"/>
+
+ <request name="surface_create">
+ <description summary="create ivi_surface with numeric ID in ivi compositor">
+ surface_create will create a interface:ivi_surface with numeric ID; surface_id in
+ ivi compositor. These surface_ids are defined as unique in the system to identify
+ it inside of ivi compositor. The ivi compositor implements business logic how to
+ set properties of the surface with surface_id according to status of the system.
+ E.g. a unique ID for Car Navigation application is used for implementing special
+ logic of the application about where it shall be located. Created ivi_surface
+ notifies warnings when following situation happens,
+ - Invalid wl_surface is set. This happen if wl_surface is destroy before this.
+ - surface_id is already assigned by another application.
+ </description>
+ <arg name="id_surface" type="uint"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="id" type="new_id" interface="ivi_surface"/>
+ </request>
+
+ </interface>
+
+</protocol>
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 09:54:41 UTC
Permalink
Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
protocol/Makefile.am | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/protocol/Makefile.am b/protocol/Makefile.am
index 5e331a7..9913f16 100644
--- a/protocol/Makefile.am
+++ b/protocol/Makefile.am
@@ -8,7 +8,8 @@ protocol_sources = \
text-cursor-position.xml \
wayland-test.xml \
xdg-shell.xml \
- scaler.xml
+ scaler.xml \
+ ivi-application.xml

if HAVE_XMLLINT
.PHONY: validate
--
1.8.3.1
Pekka Paalanen
2014-03-10 10:00:20 UTC
Permalink
On Thu, 6 Mar 2014 18:54:41 +0900
Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:

> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> ---
> protocol/Makefile.am | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/protocol/Makefile.am b/protocol/Makefile.am
> index 5e331a7..9913f16 100644
> --- a/protocol/Makefile.am
> +++ b/protocol/Makefile.am
> @@ -8,7 +8,8 @@ protocol_sources = \
> text-cursor-position.xml \
> wayland-test.xml \
> xdg-shell.xml \
> - scaler.xml
> + scaler.xml \
> + ivi-application.xml
>
> if HAVE_XMLLINT
> .PHONY: validate

Hi,

you can squash this into the patch that adds the .xml file.


Thanks,
pq
Nobuhiko Tanibata
2014-03-11 05:54:04 UTC
Permalink
Hi pq,

I will embed this patch to previous one.
Regarding other patch, I also did the same thing, I will enclose update
of Makefile to corresponding patch which update e.g. *.c.

BR,
Nobuhiko

2014-03-10 19:00 ? Pekka Paalanen ????????:
> On Thu, 6 Mar 2014 18:54:41 +0900
> Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>
>> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
>> ---
>> protocol/Makefile.am | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/protocol/Makefile.am b/protocol/Makefile.am
>> index 5e331a7..9913f16 100644
>> --- a/protocol/Makefile.am
>> +++ b/protocol/Makefile.am
>> @@ -8,7 +8,8 @@ protocol_sources = \
>> text-cursor-position.xml \
>> wayland-test.xml \
>> xdg-shell.xml \
>> - scaler.xml
>> + scaler.xml \
>> + ivi-application.xml
>>
>> if HAVE_XMLLINT
>> .PHONY: validate
>
> Hi,
>
> you can squash this into the patch that adds the .xml file.
>
>
> Thanks,
> pq
Nobuhiko Tanibata
2014-03-06 09:56:58 UTC
Permalink
In-Vehicle Infotainment system traditionally manages surfaces with global
identification. A protocol, ivi_application, supports such a feature by
implementing a request, ivi_application::surface_creation defined in
ivi_application.xml. Additionally, it initialize a library, weston-layout,
to manage properties of surfaces and group surfaces in layer. In detail,
refer library, weston_layout.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
ivi-shell/ivi-shell.c | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 333 insertions(+)
create mode 100644 ivi-shell/ivi-shell.c

diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c
new file mode 100644
index 0000000..f4c4d25
--- /dev/null
+++ b/ivi-shell/ivi-shell.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+/**
+ * ivi-shell supports a type of shell for In-Vehicle Infotainment system.
+ * In-Vehicle Infotainment system traditionally manages surfaces with global
+ * identification. A protocol, ivi_application, supports such a feature
+ * by implementing a request, ivi_application::surface_creation defined in
+ * ivi_application.xml.
+ *
+ * Additionally, it initialize a library, weston-layout, to manage properties of
+ * surfaces and group surfaces in layer. In detail, refer weston_layout.
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+
+#include "compositor.h"
+#include "ivi-application-server-protocol.h"
+#include "weston-layout.h"
+
+struct ivi_shell;
+
+struct ivi_shell_surface
+{
+ struct ivi_shell *shell;
+ struct weston_layout_surface *layout_surface;
+
+ struct weston_surface *surface;
+ uint32_t id_surface;
+
+ int32_t width;
+ int32_t height;
+
+ struct wl_list link;
+};
+
+struct ivi_shell
+{
+ struct wl_resource *resource;
+ struct wl_listener destroy_listener;
+
+ struct weston_compositor *compositor;
+ struct weston_seat *seat;
+
+ struct wl_list list_surface;
+};
+
+/* ------------------------------------------------------------------------- */
+/* common functions */
+/* ------------------------------------------------------------------------- */
+
+static void
+configure(struct weston_view *view, float x, float y)
+{
+ if (view != NULL) {
+ weston_view_set_position(view, x, y);
+ weston_view_update_transform(view);
+ }
+}
+
+/**
+ * Implementation of ivi_surface
+ */
+
+static void
+ivi_shell_surface_configure(struct weston_surface *, int32_t, int32_t);
+
+static struct ivi_shell_surface *
+get_ivi_shell_surface(struct weston_surface *surface)
+{
+ if (surface->configure == ivi_shell_surface_configure) {
+ return surface->configure_private;
+ } else {
+ return NULL;
+ }
+}
+
+static void
+ivi_shell_surface_configure(struct weston_surface *es,
+ int32_t sx, int32_t sy)
+{
+ struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(es);
+ struct weston_view *view = NULL;
+ float from_x = 0.0f;
+ float from_y = 0.0f;
+ float to_x = 0.0f;
+ float to_y = 0.0f;
+
+ if ((es->width == 0) || (es->height == 0) || (ivisurf == NULL)) {
+ return;
+ }
+
+ view = weston_layout_get_weston_view(ivisurf->layout_surface);
+ if (view == NULL) {
+ return;
+ }
+
+ if (ivisurf->width != es->width || ivisurf->height != es->height) {
+
+ ivisurf->width = es->width;
+ ivisurf->height = es->height;
+
+ weston_view_to_global_float(view, 0, 0, &from_x, &from_y);
+ weston_view_to_global_float(view, sx, sy, &to_x, &to_y);
+ configure(view,
+ view->geometry.x + to_x - from_x,
+ view->geometry.y + to_y - from_y);
+
+ weston_layout_surfaceConfigure(ivisurf->layout_surface, es->width, es->height);
+ }
+}
+
+static void
+surface_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct ivi_shell_surface *ivisurf = wl_resource_get_user_data(resource);
+ struct ivi_shell *shell = ivisurf->shell;
+
+ weston_layout_surfaceRemove(ivisurf->layout_surface);
+
+ ivisurf->surface->configure = NULL;
+ ivisurf->surface->configure_private = NULL;
+
+ if (!wl_list_empty(&ivisurf->link)) {
+ wl_list_remove(&ivisurf->link);
+ }
+ wl_list_init(&shell->list_surface);
+
+ free(ivisurf);
+ ivisurf = NULL;
+}
+
+static const struct ivi_surface_interface surface_implementation = {
+ surface_destroy,
+};
+
+static struct ivi_shell_surface *
+is_surf_in_surfaces(struct wl_list *list_surf, uint32_t id_surface)
+{
+ struct ivi_shell_surface *ivisurf;
+
+ wl_list_for_each(ivisurf, list_surf, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Implementation of ivi_application::surface_create.
+ * Creating new ivi_shell_surface with identification to identify the surface
+ * in the system.
+ */
+static void
+application_surface_create(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id_surface,
+ struct wl_resource *surface_resource,
+ uint32_t id)
+{
+ struct ivi_shell *shell = wl_resource_get_user_data(resource);
+ struct weston_layout_surface *layout_surface = NULL;
+ struct ivi_shell_surface *ivisurf = NULL;
+ struct weston_surface *es = NULL;
+
+ es = wl_resource_get_user_data(surface_resource);
+ if (es == NULL) {
+ weston_log("application_surface_create: invalid surface\n");
+ return;
+ }
+
+ ivisurf = is_surf_in_surfaces(&shell->list_surface, id_surface);
+
+ layout_surface = weston_layout_surfaceCreate(es, id_surface);
+ if (layout_surface == NULL) {
+//FIXME
+ weston_log("id_surface is already created\n");
+
+ ivisurf->surface = es;
+ ivisurf->width = 0;
+ ivisurf->height = 0;
+
+ es->configure = ivi_shell_surface_configure;
+ es->configure_private = ivisurf;
+
+ resource = wl_resource_create(client, &ivi_surface_interface, 1, id);
+ if (resource == NULL) {
+ weston_log("couldn't get surface object");
+ return;
+ }
+
+ wl_resource_set_implementation(resource,
+ &surface_implementation,
+ ivisurf, NULL);
+ return;
+ }
+
+ ivisurf = calloc(1, sizeof *ivisurf);
+ if (ivisurf == NULL) {
+ weston_log("fails to allocate memory\n");
+ return;
+ }
+
+ wl_list_init(&ivisurf->link);
+ ivisurf->shell = shell;
+ ivisurf->layout_surface = layout_surface;
+ ivisurf->surface = es;
+ ivisurf->id_surface = id_surface;
+ ivisurf->width = 0;
+ ivisurf->height = 0;
+
+ es->configure = ivi_shell_surface_configure;
+ es->configure_private = ivisurf;
+
+ wl_list_insert(&shell->list_surface, &ivisurf->link);
+
+ resource = wl_resource_create(client, &ivi_surface_interface, 1, id);
+ if (resource == NULL) {
+ weston_log("couldn't get surface object");
+ return;
+ }
+
+ wl_resource_set_implementation(resource,
+ &surface_implementation,
+ ivisurf, NULL);
+}
+
+static const struct ivi_application_interface application_implementation = {
+ application_surface_create
+};
+
+static void
+bind_ivi_application(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct ivi_shell *shell = data;
+ struct wl_resource *resource = NULL;
+
+ resource = wl_resource_create(client, &ivi_application_interface, 1, id);
+
+ wl_resource_set_implementation(resource,
+ &application_implementation,
+ shell, NULL);
+}
+
+/**
+ * Initialization/destruction method of ivi-shell
+ */
+static void
+shell_destroy(struct wl_listener *listener, void *data)
+{
+ struct ivi_shell *shell = NULL;
+
+ shell = container_of(listener, struct ivi_shell, destroy_listener);
+
+ free(shell);
+ shell = NULL;
+}
+
+static void
+init_ivi_shell(struct weston_compositor *ec, struct ivi_shell *shell)
+{
+ shell->compositor = ec;
+
+ wl_list_init(&ec->layer_list);
+ wl_list_init(&shell->list_surface);
+}
+
+/**
+ * Initialization of ivi-shell. A library, weston_layout, is also initialized
+ * here by calling weston_layout_initWithCompositor.
+ *
+ */
+
+WL_EXPORT int
+module_init(struct weston_compositor *ec,
+ int *argc, char *argv[])
+{
+ struct ivi_shell *shell = NULL;
+ struct weston_seat *seat = NULL;
+
+ shell = calloc(1, sizeof *shell);
+ if (shell == NULL) {
+ return -1;
+ }
+
+ init_ivi_shell(ec, shell);
+ weston_layout_initWithCompositor(ec);
+
+ shell->destroy_listener.notify = shell_destroy;
+ wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
+
+ if (wl_global_create(ec->wl_display, &ivi_application_interface, 1,
+ shell, bind_ivi_application) == NULL) {
+ return -1;
+ }
+
+ wl_list_for_each(seat, &ec->seat_list, link) {
+ if (seat) {
+ shell->seat = seat;
+ }
+ }
+
+ return 0;
+}
--
1.8.3.1
Pekka Paalanen
2014-03-10 10:47:58 UTC
Permalink
On Thu, 6 Mar 2014 18:56:58 +0900
Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:

> In-Vehicle Infotainment system traditionally manages surfaces with global
> identification. A protocol, ivi_application, supports such a feature by
> implementing a request, ivi_application::surface_creation defined in
> ivi_application.xml. Additionally, it initialize a library, weston-layout,
> to manage properties of surfaces and group surfaces in layer. In detail,
> refer library, weston_layout.
>
> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> ---
> ivi-shell/ivi-shell.c | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 333 insertions(+)
> create mode 100644 ivi-shell/ivi-shell.c
>
> diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c
> new file mode 100644
> index 0000000..f4c4d25
> --- /dev/null
> +++ b/ivi-shell/ivi-shell.c
> @@ -0,0 +1,333 @@
> +/*
> + * Copyright (C) 2013 DENSO CORPORATION
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and
> + * its documentation for any purpose is hereby granted without fee, provided
> + * that the above copyright notice appear in all copies and that both that
> + * copyright notice and this permission notice appear in supporting
> + * documentation, and that the name of the copyright holders not be used in
> + * advertising or publicity pertaining to distribution of the software
> + * without specific, written prior permission. The copyright holders make
> + * no representations about the suitability of this software for any
> + * purpose. It is provided "as is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
> + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
> + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
> + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
> + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
> + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +
> +/**
> + * ivi-shell supports a type of shell for In-Vehicle Infotainment system.
> + * In-Vehicle Infotainment system traditionally manages surfaces with global
> + * identification. A protocol, ivi_application, supports such a feature
> + * by implementing a request, ivi_application::surface_creation defined in
> + * ivi_application.xml.
> + *
> + * Additionally, it initialize a library, weston-layout, to manage properties of
> + * surfaces and group surfaces in layer. In detail, refer weston_layout.
> + */
> +
> +#include <sys/wait.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <linux/input.h>
> +
> +#include "compositor.h"
> +#include "ivi-application-server-protocol.h"
> +#include "weston-layout.h"

weston-layout.h is introduced in the following patch, so this patch
won't build, breaking bisectability if this series was applied.

> +
> +struct ivi_shell;
> +
> +struct ivi_shell_surface
> +{
> + struct ivi_shell *shell;
> + struct weston_layout_surface *layout_surface;
> +
> + struct weston_surface *surface;
> + uint32_t id_surface;
> +
> + int32_t width;
> + int32_t height;
> +
> + struct wl_list link;
> +};
> +
> +struct ivi_shell
> +{
> + struct wl_resource *resource;
> + struct wl_listener destroy_listener;
> +
> + struct weston_compositor *compositor;
> + struct weston_seat *seat;

'compositor' and 'seat' seem pretty unused?

> +
> + struct wl_list list_surface;

We prefer the convention <something>_list instead. Personally, I've
also added a comment about what is in this list, like
/* ivi_shell_surface::link */ because that is an invariant.

> +};
> +
> +/* ------------------------------------------------------------------------- */
> +/* common functions */
> +/* ------------------------------------------------------------------------- */
> +
> +static void
> +configure(struct weston_view *view, float x, float y)
> +{
> + if (view != NULL) {
> + weston_view_set_position(view, x, y);
> + weston_view_update_transform(view);

Something in this feels odd... the part about calling
weston_view_update_transform() manually... is that ok, or should it be
called only when mapping the surface?

> + }
> +}
> +
> +/**
> + * Implementation of ivi_surface
> + */
> +
> +static void
> +ivi_shell_surface_configure(struct weston_surface *, int32_t, int32_t);
> +
> +static struct ivi_shell_surface *
> +get_ivi_shell_surface(struct weston_surface *surface)
> +{
> + if (surface->configure == ivi_shell_surface_configure) {
> + return surface->configure_private;
> + } else {
> + return NULL;
> + }
> +}
> +
> +static void
> +ivi_shell_surface_configure(struct weston_surface *es,
> + int32_t sx, int32_t sy)
> +{
> + struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(es);
> + struct weston_view *view = NULL;
> + float from_x = 0.0f;
> + float from_y = 0.0f;
> + float to_x = 0.0f;
> + float to_y = 0.0f;
> +
> + if ((es->width == 0) || (es->height == 0) || (ivisurf == NULL)) {
> + return;
> + }
> +
> + view = weston_layout_get_weston_view(ivisurf->layout_surface);
> + if (view == NULL) {
> + return;
> + }
> +
> + if (ivisurf->width != es->width || ivisurf->height != es->height) {
> +
> + ivisurf->width = es->width;
> + ivisurf->height = es->height;
> +
> + weston_view_to_global_float(view, 0, 0, &from_x, &from_y);
> + weston_view_to_global_float(view, sx, sy, &to_x, &to_y);
> + configure(view,
> + view->geometry.x + to_x - from_x,
> + view->geometry.y + to_y - from_y);
> +
> + weston_layout_surfaceConfigure(ivisurf->layout_surface, es->width, es->height);
> + }
> +}
> +
> +static void
> +surface_destroy(struct wl_client *client,
> + struct wl_resource *resource)
> +{
> + struct ivi_shell_surface *ivisurf = wl_resource_get_user_data(resource);
> + struct ivi_shell *shell = ivisurf->shell;
> +
> + weston_layout_surfaceRemove(ivisurf->layout_surface);
> +
> + ivisurf->surface->configure = NULL;
> + ivisurf->surface->configure_private = NULL;
> +
> + if (!wl_list_empty(&ivisurf->link)) {
> + wl_list_remove(&ivisurf->link);
> + }
> + wl_list_init(&shell->list_surface);
> +
> + free(ivisurf);
> + ivisurf = NULL;

Local variable.

I just realized that your protocol spec does not define what should
happen on destruction.

> +}
> +
> +static const struct ivi_surface_interface surface_implementation = {
> + surface_destroy,
> +};
> +
> +static struct ivi_shell_surface *
> +is_surf_in_surfaces(struct wl_list *list_surf, uint32_t id_surface)
> +{
> + struct ivi_shell_surface *ivisurf;
> +
> + wl_list_for_each(ivisurf, list_surf, link) {
> + if (ivisurf->id_surface == id_surface) {
> + return ivisurf;
> + }
> + }
> +
> + return NULL;
> +}
> +
> +/**
> + * Implementation of ivi_application::surface_create.
> + * Creating new ivi_shell_surface with identification to identify the surface
> + * in the system.
> + */
> +static void
> +application_surface_create(struct wl_client *client,
> + struct wl_resource *resource,
> + uint32_t id_surface,
> + struct wl_resource *surface_resource,
> + uint32_t id)
> +{
> + struct ivi_shell *shell = wl_resource_get_user_data(resource);
> + struct weston_layout_surface *layout_surface = NULL;
> + struct ivi_shell_surface *ivisurf = NULL;
> + struct weston_surface *es = NULL;
> +
> + es = wl_resource_get_user_data(surface_resource);
> + if (es == NULL) {
> + weston_log("application_surface_create: invalid surface\n");
> + return;
> + }
> +
> + ivisurf = is_surf_in_surfaces(&shell->list_surface, id_surface);
> +
> + layout_surface = weston_layout_surfaceCreate(es, id_surface);
> + if (layout_surface == NULL) {
> +//FIXME

Forgot something?
Seems like double-checking the same thing, slightly confusing. Avoid
calling weston_layout_surfaceCreate() to begin with, if (ivisurf)?

> + weston_log("id_surface is already created\n");
> +
> + ivisurf->surface = es;
> + ivisurf->width = 0;
> + ivisurf->height = 0;
> +
> + es->configure = ivi_shell_surface_configure;
> + es->configure_private = ivisurf;
> +
> + resource = wl_resource_create(client, &ivi_surface_interface, 1, id);
> + if (resource == NULL) {
> + weston_log("couldn't get surface object");
> + return;
> + }
> +
> + wl_resource_set_implementation(resource,
> + &surface_implementation,
> + ivisurf, NULL);

Does this mean, that if a client calls ivi_application.surface_create
with an already used ID, it will get a handle to the existing
ivi_shell_surface? Is that supposed to work? If yes, then
ivi_shell_surface needs a list of all wl_resources pointing to it.

IDs are global, aren't they? So it could get a handle to some *other*
client's ivi_shell_surface. That doesn't sound good.

> + return;
> + }
> +
> + ivisurf = calloc(1, sizeof *ivisurf);
> + if (ivisurf == NULL) {
> + weston_log("fails to allocate memory\n");
> + return;
> + }
> +
> + wl_list_init(&ivisurf->link);
> + ivisurf->shell = shell;
> + ivisurf->layout_surface = layout_surface;
> + ivisurf->surface = es;
> + ivisurf->id_surface = id_surface;
> + ivisurf->width = 0;
> + ivisurf->height = 0;
> +
> + es->configure = ivi_shell_surface_configure;
> + es->configure_private = ivisurf;
> +
> + wl_list_insert(&shell->list_surface, &ivisurf->link);
> +
> + resource = wl_resource_create(client, &ivi_surface_interface, 1, id);
> + if (resource == NULL) {
> + weston_log("couldn't get surface object");
> + return;
> + }
> +
> + wl_resource_set_implementation(resource,
> + &surface_implementation,
> + ivisurf, NULL);

Are you sure you don't need a destructor here? If the client
disconnects without explicitly destroying all its protocol objects, how
does ivisurf get freed?

> +}
> +
> +static const struct ivi_application_interface application_implementation = {
> + application_surface_create
> +};
> +
> +static void
> +bind_ivi_application(struct wl_client *client,
> + void *data, uint32_t version, uint32_t id)
> +{
> + struct ivi_shell *shell = data;
> + struct wl_resource *resource = NULL;
> +
> + resource = wl_resource_create(client, &ivi_application_interface, 1, id);
> +
> + wl_resource_set_implementation(resource,
> + &application_implementation,
> + shell, NULL);
> +}
> +
> +/**
> + * Initialization/destruction method of ivi-shell
> + */
> +static void
> +shell_destroy(struct wl_listener *listener, void *data)
> +{
> + struct ivi_shell *shell = NULL;
> +
> + shell = container_of(listener, struct ivi_shell, destroy_listener);
> +
> + free(shell);
> + shell = NULL;

Nulling a local variable again.

I think you should do some sanity/leak checks here, like ensuring that
the surface list is empty, no?

> +}
> +
> +static void
> +init_ivi_shell(struct weston_compositor *ec, struct ivi_shell *shell)
> +{
> + shell->compositor = ec;
> +
> + wl_list_init(&ec->layer_list);
> + wl_list_init(&shell->list_surface);
> +}
> +
> +/**
> + * Initialization of ivi-shell. A library, weston_layout, is also initialized
> + * here by calling weston_layout_initWithCompositor.
> + *
> + */
> +
> +WL_EXPORT int
> +module_init(struct weston_compositor *ec,
> + int *argc, char *argv[])
> +{
> + struct ivi_shell *shell = NULL;
> + struct weston_seat *seat = NULL;
> +
> + shell = calloc(1, sizeof *shell);
> + if (shell == NULL) {
> + return -1;
> + }
> +
> + init_ivi_shell(ec, shell);
> + weston_layout_initWithCompositor(ec);

It's kind of surprising... this module's init requires another module to
have been loaded before, otherwise this module will not load, right?
I wonder if you get a sensible error message when that happens.

> +
> + shell->destroy_listener.notify = shell_destroy;
> + wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
> +
> + if (wl_global_create(ec->wl_display, &ivi_application_interface, 1,
> + shell, bind_ivi_application) == NULL) {
> + return -1;
> + }
> +
> + wl_list_for_each(seat, &ec->seat_list, link) {
> + if (seat) {
> + shell->seat = seat;

'seat' cannot be NULL here. It seems you are assuming that there can be
only one seat? Why?

> + }
> + }
> +
> + return 0;
> +}


Thanks,
pq
Nobuhiko Tanibata
2014-03-11 05:51:21 UTC
Permalink
2014-03-10 19:47 ? Pekka Paalanen ????????:
> On Thu, 6 Mar 2014 18:56:58 +0900
> Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>
>> In-Vehicle Infotainment system traditionally manages surfaces with
>> global
>> identification. A protocol, ivi_application, supports such a feature
>> by
>> implementing a request, ivi_application::surface_creation defined in
>> ivi_application.xml. Additionally, it initialize a library,
>> weston-layout,
>> to manage properties of surfaces and group surfaces in layer. In
>> detail,
>> refer library, weston_layout.
>>
>> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
>> ---
>> ivi-shell/ivi-shell.c | 333
>> ++++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 333 insertions(+)
>> create mode 100644 ivi-shell/ivi-shell.c
>>
>> diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c
>> new file mode 100644
>> index 0000000..f4c4d25
>> --- /dev/null
>> +++ b/ivi-shell/ivi-shell.c
>> @@ -0,0 +1,333 @@
>> +/*
>> + * Copyright (C) 2013 DENSO CORPORATION
>> + *
>> + * Permission to use, copy, modify, distribute, and sell this
>> software and
>> + * its documentation for any purpose is hereby granted without fee,
>> provided
>> + * that the above copyright notice appear in all copies and that both
>> that
>> + * copyright notice and this permission notice appear in supporting
>> + * documentation, and that the name of the copyright holders not be
>> used in
>> + * advertising or publicity pertaining to distribution of the
>> software
>> + * without specific, written prior permission. The copyright holders
>> make
>> + * no representations about the suitability of this software for any
>> + * purpose. It is provided "as is" without express or implied
>> warranty.
>> + *
>> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
>> + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
>> + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
>> + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
>> WHATSOEVER
>> + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
>> OF
>> + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
>> IN
>> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +
>> +/**
>> + * ivi-shell supports a type of shell for In-Vehicle Infotainment
>> system.
>> + * In-Vehicle Infotainment system traditionally manages surfaces with
>> global
>> + * identification. A protocol, ivi_application, supports such a
>> feature
>> + * by implementing a request, ivi_application::surface_creation
>> defined in
>> + * ivi_application.xml.
>> + *
>> + * Additionally, it initialize a library, weston-layout, to manage
>> properties of
>> + * surfaces and group surfaces in layer. In detail, refer
>> weston_layout.
>> + */
>> +
>> +#include <sys/wait.h>
>> +#include <unistd.h>
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <linux/input.h>
>> +
>> +#include "compositor.h"
>> +#include "ivi-application-server-protocol.h"
>> +#include "weston-layout.h"
>
> weston-layout.h is introduced in the following patch, so this patch
> won't build, breaking bisectability if this series was applied.
>

I agree.

>> +
>> +struct ivi_shell;
>> +
>> +struct ivi_shell_surface
>> +{
>> + struct ivi_shell *shell;
>> + struct weston_layout_surface *layout_surface;
>> +
>> + struct weston_surface *surface;
>> + uint32_t id_surface;
>> +
>> + int32_t width;
>> + int32_t height;
>> +
>> + struct wl_list link;
>> +};
>> +
>> +struct ivi_shell
>> +{
>> + struct wl_resource *resource;
>> + struct wl_listener destroy_listener;
>> +
>> + struct weston_compositor *compositor;
>> + struct weston_seat *seat;
>
> 'compositor' and 'seat' seem pretty unused?
>
>> +
>> + struct wl_list list_surface;
>
> We prefer the convention <something>_list instead. Personally, I've
> also added a comment about what is in this list, like
> /* ivi_shell_surface::link */ because that is an invariant.

I agree.

>
>> +};
>> +
>> +/*
>> ------------------------------------------------------------------------- */
>> +/* common functions
>> */
>> +/*
>> ------------------------------------------------------------------------- */
>> +
>> +static void
>> +configure(struct weston_view *view, float x, float y)
>> +{
>> + if (view != NULL) {
>> + weston_view_set_position(view, x, y);
>> + weston_view_update_transform(view);
>
> Something in this feels odd... the part about calling
> weston_view_update_transform() manually... is that ok, or should it be
> called only when mapping the surface?
>

I move the above code to below.

>> + }
>> +}
>> +
>> +/**
>> + * Implementation of ivi_surface
>> + */
>> +
>> +static void
>> +ivi_shell_surface_configure(struct weston_surface *, int32_t,
>> int32_t);
>> +
>> +static struct ivi_shell_surface *
>> +get_ivi_shell_surface(struct weston_surface *surface)
>> +{
>> + if (surface->configure == ivi_shell_surface_configure) {
>> + return surface->configure_private;
>> + } else {
>> + return NULL;
>> + }
>> +}
>> +
>> +static void
>> +ivi_shell_surface_configure(struct weston_surface *es,
>> + int32_t sx, int32_t sy)
>> +{
>> + struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(es);
>> + struct weston_view *view = NULL;
>> + float from_x = 0.0f;
>> + float from_y = 0.0f;
>> + float to_x = 0.0f;
>> + float to_y = 0.0f;
>> +
>> + if ((es->width == 0) || (es->height == 0) || (ivisurf == NULL)) {
>> + return;
>> + }
>> +
>> + view = weston_layout_get_weston_view(ivisurf->layout_surface);
>> + if (view == NULL) {
>> + return;
>> + }
>> +
>> + if (ivisurf->width != es->width || ivisurf->height != es->height)
>> {
>> +
>> + ivisurf->width = es->width;
>> + ivisurf->height = es->height;
>> +
>> + weston_view_to_global_float(view, 0, 0, &from_x, &from_y);
>> + weston_view_to_global_float(view, sx, sy, &to_x, &to_y);
>> + configure(view,
>> + view->geometry.x + to_x - from_x,
>> + view->geometry.y + to_y - from_y);
>> +
>> + weston_layout_surfaceConfigure(ivisurf->layout_surface,
>> es->width, es->height);
>> + }
>> +}
>> +
>> +static void
>> +surface_destroy(struct wl_client *client,
>> + struct wl_resource *resource)
>> +{
>> + struct ivi_shell_surface *ivisurf =
>> wl_resource_get_user_data(resource);
>> + struct ivi_shell *shell = ivisurf->shell;
>> +
>> + weston_layout_surfaceRemove(ivisurf->layout_surface);
>> +
>> + ivisurf->surface->configure = NULL;
>> + ivisurf->surface->configure_private = NULL;
>> +
>> + if (!wl_list_empty(&ivisurf->link)) {
>> + wl_list_remove(&ivisurf->link);
>> + }
>> + wl_list_init(&shell->list_surface);
>> +
>> + free(ivisurf);
>> + ivisurf = NULL;
>
> Local variable.
>
> I just realized that your protocol spec does not define what should
> happen on destruction.

I will add description to ivi_application.xml.

>
>> +}
>> +
>> +static const struct ivi_surface_interface surface_implementation = {
>> + surface_destroy,
>> +};
>> +
>> +static struct ivi_shell_surface *
>> +is_surf_in_surfaces(struct wl_list *list_surf, uint32_t id_surface)
>> +{
>> + struct ivi_shell_surface *ivisurf;
>> +
>> + wl_list_for_each(ivisurf, list_surf, link) {
>> + if (ivisurf->id_surface == id_surface) {
>> + return ivisurf;
>> + }
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +/**
>> + * Implementation of ivi_application::surface_create.
>> + * Creating new ivi_shell_surface with identification to identify the
>> surface
>> + * in the system.
>> + */
>> +static void
>> +application_surface_create(struct wl_client *client,
>> + struct wl_resource *resource,
>> + uint32_t id_surface,
>> + struct wl_resource *surface_resource,
>> + uint32_t id)
>> +{
>> + struct ivi_shell *shell = wl_resource_get_user_data(resource);
>> + struct weston_layout_surface *layout_surface = NULL;
>> + struct ivi_shell_surface *ivisurf = NULL;
>> + struct weston_surface *es = NULL;
>> +
>> + es = wl_resource_get_user_data(surface_resource);
>> + if (es == NULL) {
>> + weston_log("application_surface_create: invalid surface\n");
>> + return;
>> + }
>> +
>> + ivisurf = is_surf_in_surfaces(&shell->list_surface, id_surface);
>> +
>> + layout_surface = weston_layout_surfaceCreate(es, id_surface);
>> + if (layout_surface == NULL) {
>> +//FIXME
>
> Forgot something?
> Seems like double-checking the same thing, slightly confusing. Avoid
> calling weston_layout_surfaceCreate() to begin with, if (ivisurf)?
>
>> + weston_log("id_surface is already created\n");
>> +
>> + ivisurf->surface = es;
>> + ivisurf->width = 0;
>> + ivisurf->height = 0;
>> +
>> + es->configure = ivi_shell_surface_configure;
>> + es->configure_private = ivisurf;
>> +
>> + resource = wl_resource_create(client, &ivi_surface_interface,
>> 1, id);
>> + if (resource == NULL) {
>> + weston_log("couldn't get surface object");
>> + return;
>> + }
>> +
>> + wl_resource_set_implementation(resource,
>> + &surface_implementation,
>> + ivisurf, NULL);
>
> Does this mean, that if a client calls ivi_application.surface_create
> with an already used ID, it will get a handle to the existing
> ivi_shell_surface? Is that supposed to work? If yes, then
> ivi_shell_surface needs a list of all wl_resources pointing to it.
>
> IDs are global, aren't they? So it could get a handle to some *other*
> client's ivi_shell_surface. That doesn't sound good.
>

I will realign warning in ivi_application.xml and update the above code.
Basically, I agree with your comments.

>> + return;
>> + }
>> +
>> + ivisurf = calloc(1, sizeof *ivisurf);
>> + if (ivisurf == NULL) {
>> + weston_log("fails to allocate memory\n");
>> + return;
>> + }
>> +
>> + wl_list_init(&ivisurf->link);
>> + ivisurf->shell = shell;
>> + ivisurf->layout_surface = layout_surface;
>> + ivisurf->surface = es;
>> + ivisurf->id_surface = id_surface;
>> + ivisurf->width = 0;
>> + ivisurf->height = 0;
>> +
>> + es->configure = ivi_shell_surface_configure;
>> + es->configure_private = ivisurf;
>> +
>> + wl_list_insert(&shell->list_surface, &ivisurf->link);
>> +
>> + resource = wl_resource_create(client, &ivi_surface_interface, 1,
>> id);
>> + if (resource == NULL) {
>> + weston_log("couldn't get surface object");
>> + return;
>> + }
>> +
>> + wl_resource_set_implementation(resource,
>> + &surface_implementation,
>> + ivisurf, NULL);
>
> Are you sure you don't need a destructor here? If the client
> disconnects without explicitly destroying all its protocol objects, how
> does ivisurf get freed?
>
I agree.

>> +}
>> +
>> +static const struct ivi_application_interface
>> application_implementation = {
>> + application_surface_create
>> +};
>> +
>> +static void
>> +bind_ivi_application(struct wl_client *client,
>> + void *data, uint32_t version, uint32_t id)
>> +{
>> + struct ivi_shell *shell = data;
>> + struct wl_resource *resource = NULL;
>> +
>> + resource = wl_resource_create(client, &ivi_application_interface,
>> 1, id);
>> +
>> + wl_resource_set_implementation(resource,
>> + &application_implementation,
>> + shell, NULL);
>> +}
>> +
>> +/**
>> + * Initialization/destruction method of ivi-shell
>> + */
>> +static void
>> +shell_destroy(struct wl_listener *listener, void *data)
>> +{
>> + struct ivi_shell *shell = NULL;
>> +
>> + shell = container_of(listener, struct ivi_shell,
>> destroy_listener);
>> +
>> + free(shell);
>> + shell = NULL;
>
> Nulling a local variable again.
>
> I think you should do some sanity/leak checks here, like ensuring that
> the surface list is empty, no?

I agree. This is just my habit.

>
>> +}
>> +
>> +static void
>> +init_ivi_shell(struct weston_compositor *ec, struct ivi_shell *shell)
>> +{
>> + shell->compositor = ec;
>> +
>> + wl_list_init(&ec->layer_list);
>> + wl_list_init(&shell->list_surface);
>> +}
>> +
>> +/**
>> + * Initialization of ivi-shell. A library, weston_layout, is also
>> initialized
>> + * here by calling weston_layout_initWithCompositor.
>> + *
>> + */
>> +
>> +WL_EXPORT int
>> +module_init(struct weston_compositor *ec,
>> + int *argc, char *argv[])
>> +{
>> + struct ivi_shell *shell = NULL;
>> + struct weston_seat *seat = NULL;
>> +
>> + shell = calloc(1, sizeof *shell);
>> + if (shell == NULL) {
>> + return -1;
>> + }
>> +
>> + init_ivi_shell(ec, shell);
>> + weston_layout_initWithCompositor(ec);
>
> It's kind of surprising... this module's init requires another module
> to
> have been loaded before, otherwise this module will not load, right?
> I wonder if you get a sensible error message when that happens.

westen_layout is not a module to be loaded by ivi-shell. It is shared
library.
If it is not weston manner, I can link it statically. Please give me
your suggestion?

>
>> +
>> + shell->destroy_listener.notify = shell_destroy;
>> + wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
>> +
>> + if (wl_global_create(ec->wl_display, &ivi_application_interface,
>> 1,
>> + shell, bind_ivi_application) == NULL) {
>> + return -1;
>> + }
>> +
>> + wl_list_for_each(seat, &ec->seat_list, link) {
>> + if (seat) {
>> + shell->seat = seat;
>
> 'seat' cannot be NULL here. It seems you are assuming that there can be
> only one seat? Why?
>

Ideally, I agree. However I am in automotive software, and I have habit
to avoid NULL access as much as possible in case of the worst scenario.


Thank you,
Nobuhiko
>> + }
>> + }
>> +
>> + return 0;
>> +}
>
>
> Thanks,
> pq
Pekka Paalanen
2014-03-11 08:14:31 UTC
Permalink
On Tue, 11 Mar 2014 14:51:21 +0900
Nobuhiko Tanibata <nobuhiko_tanibata at xddp.denso.co.jp> wrote:

> 2014-03-10 19:47 ? Pekka Paalanen ????????:
> > On Thu, 6 Mar 2014 18:56:58 +0900
> > Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
> >
> >> In-Vehicle Infotainment system traditionally manages surfaces with
> >> global
> >> identification. A protocol, ivi_application, supports such a feature
> >> by
> >> implementing a request, ivi_application::surface_creation defined in
> >> ivi_application.xml. Additionally, it initialize a library,
> >> weston-layout,
> >> to manage properties of surfaces and group surfaces in layer. In
> >> detail,
> >> refer library, weston_layout.
> >>
> >> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> >> ---
> >> ivi-shell/ivi-shell.c | 333
> >> ++++++++++++++++++++++++++++++++++++++++++++++++++
> >> 1 file changed, 333 insertions(+)
> >> create mode 100644 ivi-shell/ivi-shell.c

...

> >> +static void
> >> +init_ivi_shell(struct weston_compositor *ec, struct ivi_shell *shell)
> >> +{
> >> + shell->compositor = ec;
> >> +
> >> + wl_list_init(&ec->layer_list);
> >> + wl_list_init(&shell->list_surface);
> >> +}
> >> +
> >> +/**
> >> + * Initialization of ivi-shell. A library, weston_layout, is also
> >> initialized
> >> + * here by calling weston_layout_initWithCompositor.
> >> + *
> >> + */
> >> +
> >> +WL_EXPORT int
> >> +module_init(struct weston_compositor *ec,
> >> + int *argc, char *argv[])
> >> +{
> >> + struct ivi_shell *shell = NULL;
> >> + struct weston_seat *seat = NULL;
> >> +
> >> + shell = calloc(1, sizeof *shell);
> >> + if (shell == NULL) {
> >> + return -1;
> >> + }
> >> +
> >> + init_ivi_shell(ec, shell);
> >> + weston_layout_initWithCompositor(ec);
> >
> > It's kind of surprising... this module's init requires another module
> > to
> > have been loaded before, otherwise this module will not load, right?
> > I wonder if you get a sensible error message when that happens.
>
> westen_layout is not a module to be loaded by ivi-shell. It is shared
> library.
> If it is not weston manner, I can link it statically. Please give me
> your suggestion?

Oh, ok, that should be alright then. I just jumped into a conclusion
that all .so's were plugins. I stand corrected. I read these patches
one by one, when I can.

Is there a reason weston_layout should be a dynamic library? Do you
expect it's ABI to be stable, and have a use case for swapping one of
the two while keeping the other compiled binary intact?

If you are not committing to a stable library ABI, then I'd suggest not
having it as a dynamic library to avoid any confusion and abuse; to
avoid the risk of suddenly realizing you cannot change the API, because
someone else is using it or having a different implementation of it.

> >> +
> >> + shell->destroy_listener.notify = shell_destroy;
> >> + wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
> >> +
> >> + if (wl_global_create(ec->wl_display, &ivi_application_interface,
> >> 1,
> >> + shell, bind_ivi_application) == NULL) {
> >> + return -1;
> >> + }
> >> +
> >> + wl_list_for_each(seat, &ec->seat_list, link) {
> >> + if (seat) {
> >> + shell->seat = seat;
> >
> > 'seat' cannot be NULL here. It seems you are assuming that there can be
> > only one seat? Why?
> >
>
> Ideally, I agree. However I am in automotive software, and I have habit
> to avoid NULL access as much as possible in case of the worst scenario.

Then put an assert(), though in this case even that would be too much.
You can never get a NULL from wl_list_for_each(). You might get a bad
pointer if the list is corrupted, but the odds of getting exactly NULL
are diminishing even with corruption.

Silently ignoring NULLs where they should never appear may hide real
problems in testing, and even in production you'd probably want to log
it somehow to help post mortem.


Thanks,
pq
Nobuhiko Tanibata
2014-03-11 16:31:38 UTC
Permalink
2014-03-11 17:14 ? Pekka Paalanen ????????:
> On Tue, 11 Mar 2014 14:51:21 +0900
> Nobuhiko Tanibata <nobuhiko_tanibata at xddp.denso.co.jp> wrote:
>
>> 2014-03-10 19:47 ? Pekka Paalanen ????????:
>> > On Thu, 6 Mar 2014 18:56:58 +0900
>> > Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>> >
>> >> In-Vehicle Infotainment system traditionally manages surfaces with
>> >> global
>> >> identification. A protocol, ivi_application, supports such a feature
>> >> by
>> >> implementing a request, ivi_application::surface_creation defined in
>> >> ivi_application.xml. Additionally, it initialize a library,
>> >> weston-layout,
>> >> to manage properties of surfaces and group surfaces in layer. In
>> >> detail,
>> >> refer library, weston_layout.
>> >>
>> >> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
>> >> ---
>> >> ivi-shell/ivi-shell.c | 333
>> >> ++++++++++++++++++++++++++++++++++++++++++++++++++
>> >> 1 file changed, 333 insertions(+)
>> >> create mode 100644 ivi-shell/ivi-shell.c
>
> ...
>
>> >> +static void
>> >> +init_ivi_shell(struct weston_compositor *ec, struct ivi_shell *shell)
>> >> +{
>> >> + shell->compositor = ec;
>> >> +
>> >> + wl_list_init(&ec->layer_list);
>> >> + wl_list_init(&shell->list_surface);
>> >> +}
>> >> +
>> >> +/**
>> >> + * Initialization of ivi-shell. A library, weston_layout, is also
>> >> initialized
>> >> + * here by calling weston_layout_initWithCompositor.
>> >> + *
>> >> + */
>> >> +
>> >> +WL_EXPORT int
>> >> +module_init(struct weston_compositor *ec,
>> >> + int *argc, char *argv[])
>> >> +{
>> >> + struct ivi_shell *shell = NULL;
>> >> + struct weston_seat *seat = NULL;
>> >> +
>> >> + shell = calloc(1, sizeof *shell);
>> >> + if (shell == NULL) {
>> >> + return -1;
>> >> + }
>> >> +
>> >> + init_ivi_shell(ec, shell);
>> >> + weston_layout_initWithCompositor(ec);
>> >
>> > It's kind of surprising... this module's init requires another module
>> > to
>> > have been loaded before, otherwise this module will not load, right?
>> > I wonder if you get a sensible error message when that happens.
>>
>> westen_layout is not a module to be loaded by ivi-shell. It is shared
>> library.
>> If it is not weston manner, I can link it statically. Please give me
>> your suggestion?
>
> Oh, ok, that should be alright then. I just jumped into a conclusion
> that all .so's were plugins. I stand corrected. I read these patches
> one by one, when I can.
>
> Is there a reason weston_layout should be a dynamic library? Do you
> expect it's ABI to be stable, and have a use case for swapping one of
> the two while keeping the other compiled binary intact?
>
> If you are not committing to a stable library ABI, then I'd suggest not
> having it as a dynamic library to avoid any confusion and abuse; to
> avoid the risk of suddenly realizing you cannot change the API, because
> someone else is using it or having a different implementation of it.
>

Hi pq,

I see. I agree with your comments.

>> >> +
>> >> + shell->destroy_listener.notify = shell_destroy;
>> >> + wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
>> >> +
>> >> + if (wl_global_create(ec->wl_display, &ivi_application_interface,
>> >> 1,
>> >> + shell, bind_ivi_application) == NULL) {
>> >> + return -1;
>> >> + }
>> >> +
>> >> + wl_list_for_each(seat, &ec->seat_list, link) {
>> >> + if (seat) {
>> >> + shell->seat = seat;
>> >
>> > 'seat' cannot be NULL here. It seems you are assuming that there can be
>> > only one seat? Why?
>> >
>>
>> Ideally, I agree. However I am in automotive software, and I have
>> habit
>> to avoid NULL access as much as possible in case of the worst
>> scenario.
>
> Then put an assert(), though in this case even that would be too much.
> You can never get a NULL from wl_list_for_each(). You might get a bad
> pointer if the list is corrupted, but the odds of getting exactly NULL
> are diminishing even with corruption.
>
> Silently ignoring NULLs where they should never appear may hide real
> problems in testing, and even in production you'd probably want to log
> it somehow to help post mortem.
>
OK. I will modify my patches.

Thank you very much for many comments!

BR,
Nobuhiko

>
> Thanks,
> pq
Bill Spitzak
2014-03-11 19:10:45 UTC
Permalink
Pekka Paalanen wrote:

>>>> + wl_list_for_each(seat, &ec->seat_list, link) {
>>>> + if (seat) {
>>>> + shell->seat = seat;
>>> 'seat' cannot be NULL here. It seems you are assuming that there can be
>>> only one seat? Why?
>>>
>> Ideally, I agree. However I am in automotive software, and I have habit
>> to avoid NULL access as much as possible in case of the worst scenario.
>
> Then put an assert(), though in this case even that would be too much.
> You can never get a NULL from wl_list_for_each(). You might get a bad
> pointer if the list is corrupted, but the odds of getting exactly NULL
> are diminishing even with corruption.
>
> Silently ignoring NULLs where they should never appear may hide real
> problems in testing, and even in production you'd probably want to log
> it somehow to help post mortem.

In addition, seeing an "if (x)" is a strong indication to the programmer
that x *can* be NULL, and they will then make modifications to perceived
bugs on the assumption that NULL is a possible value. This often leads
to this same mistake being propagated to every function called by this
and every use of a variable this value is stored into.

An assert(x) however is a strong indication that x is *not* NULL.

If you really are tempted to make a test so that if you missed a bug
there is less chance of the optimized program crashing, what I do is
something like this:

assert(x);
if (!x) return; // THIS SHOULD NOT HAPPEN
Nobuhiko Tanibata
2014-03-11 23:50:18 UTC
Permalink
2014-03-12 04:10 ? Bill Spitzak ????????:
> Pekka Paalanen wrote:
>
>>>>> + wl_list_for_each(seat, &ec->seat_list, link) {
>>>>> + if (seat) {
>>>>> + shell->seat = seat;
>>>> 'seat' cannot be NULL here. It seems you are assuming that there can
>>>> be
>>>> only one seat? Why?
>>>>
>>> Ideally, I agree. However I am in automotive software, and I have
>>> habit to avoid NULL access as much as possible in case of the worst
>>> scenario.
>>
>> Then put an assert(), though in this case even that would be too much.
>> You can never get a NULL from wl_list_for_each(). You might get a bad
>> pointer if the list is corrupted, but the odds of getting exactly NULL
>> are diminishing even with corruption.
>>
>> Silently ignoring NULLs where they should never appear may hide real
>> problems in testing, and even in production you'd probably want to log
>> it somehow to help post mortem.
>
> In addition, seeing an "if (x)" is a strong indication to the
> programmer that x *can* be NULL, and they will then make modifications
> to perceived bugs on the assumption that NULL is a possible value.
> This often leads to this same mistake being propagated to every
> function called by this and every use of a variable this value is
> stored into.
>
> An assert(x) however is a strong indication that x is *not* NULL.
>
> If you really are tempted to make a test so that if you missed a bug
> there is less chance of the optimized program crashing, what I do is
> something like this:
>
> assert(x);
> if (!x) return; // THIS SHOULD NOT HAPPEN

Hi pq and Bill,

Thank you a lot. I will follow the above way.

BR,
Nobuhiko
Nobuhiko Tanibata
2014-03-14 13:18:58 UTC
Permalink
2014-03-11 17:14 ? Pekka Paalanen ????????:
> On Tue, 11 Mar 2014 14:51:21 +0900
> Nobuhiko Tanibata <nobuhiko_tanibata at xddp.denso.co.jp> wrote:
>
>> 2014-03-10 19:47 ? Pekka Paalanen ????????:
>> > On Thu, 6 Mar 2014 18:56:58 +0900
>> > Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>> >
>> >> In-Vehicle Infotainment system traditionally manages surfaces with
>> >> global
>> >> identification. A protocol, ivi_application, supports such a feature
>> >> by
>> >> implementing a request, ivi_application::surface_creation defined in
>> >> ivi_application.xml. Additionally, it initialize a library,
>> >> weston-layout,
>> >> to manage properties of surfaces and group surfaces in layer. In
>> >> detail,
>> >> refer library, weston_layout.
>> >>
>> >> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
>> >> ---
>> >> ivi-shell/ivi-shell.c | 333
>> >> ++++++++++++++++++++++++++++++++++++++++++++++++++
>> >> 1 file changed, 333 insertions(+)
>> >> create mode 100644 ivi-shell/ivi-shell.c
>
> ...
>
>> >> +static void
>> >> +init_ivi_shell(struct weston_compositor *ec, struct ivi_shell *shell)
>> >> +{
>> >> + shell->compositor = ec;
>> >> +
>> >> + wl_list_init(&ec->layer_list);
>> >> + wl_list_init(&shell->list_surface);
>> >> +}
>> >> +
>> >> +/**
>> >> + * Initialization of ivi-shell. A library, weston_layout, is also
>> >> initialized
>> >> + * here by calling weston_layout_initWithCompositor.
>> >> + *
>> >> + */
>> >> +
>> >> +WL_EXPORT int
>> >> +module_init(struct weston_compositor *ec,
>> >> + int *argc, char *argv[])
>> >> +{
>> >> + struct ivi_shell *shell = NULL;
>> >> + struct weston_seat *seat = NULL;
>> >> +
>> >> + shell = calloc(1, sizeof *shell);
>> >> + if (shell == NULL) {
>> >> + return -1;
>> >> + }
>> >> +
>> >> + init_ivi_shell(ec, shell);
>> >> + weston_layout_initWithCompositor(ec);
>> >
>> > It's kind of surprising... this module's init requires another module
>> > to
>> > have been loaded before, otherwise this module will not load, right?
>> > I wonder if you get a sensible error message when that happens.
>>
>> westen_layout is not a module to be loaded by ivi-shell. It is shared
>> library.
>> If it is not weston manner, I can link it statically. Please give me
>> your suggestion?
>
> Oh, ok, that should be alright then. I just jumped into a conclusion
> that all .so's were plugins. I stand corrected. I read these patches
> one by one, when I can.
>
> Is there a reason weston_layout should be a dynamic library? Do you
> expect it's ABI to be stable, and have a use case for swapping one of
> the two while keeping the other compiled binary intact?
>
> If you are not committing to a stable library ABI, then I'd suggest not
> having it as a dynamic library to avoid any confusion and abuse; to
> avoid the risk of suddenly realizing you cannot change the API, because
> someone else is using it or having a different implementation of it.
>

Hi pq,

I forget one important reason why weston_layout should be a dynamic
library.
At first email, I enclosed a pdf. It said ivi-controller.so which is
maintained in another repository of GENIVI. It will link weston_layout.
If I embed it in ivi-shell.so, I might need to set ivi-shell.so as
shared library
to be linked to ivi-controller.so.

These APIs are based on GENIVI layer manager APIs. So it is stable and
not be changed wihtout critical reason.

BR,
Nobuhiko

>> >> +
>> >> + shell->destroy_listener.notify = shell_destroy;
>> >> + wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
>> >> +
>> >> + if (wl_global_create(ec->wl_display, &ivi_application_interface,
>> >> 1,
>> >> + shell, bind_ivi_application) == NULL) {
>> >> + return -1;
>> >> + }
>> >> +
>> >> + wl_list_for_each(seat, &ec->seat_list, link) {
>> >> + if (seat) {
>> >> + shell->seat = seat;
>> >
>> > 'seat' cannot be NULL here. It seems you are assuming that there can be
>> > only one seat? Why?
>> >
>>
>> Ideally, I agree. However I am in automotive software, and I have
>> habit
>> to avoid NULL access as much as possible in case of the worst
>> scenario.
>
> Then put an assert(), though in this case even that would be too much.
> You can never get a NULL from wl_list_for_each(). You might get a bad
> pointer if the list is corrupted, but the odds of getting exactly NULL
> are diminishing even with corruption.
>
> Silently ignoring NULLs where they should never appear may hide real
> problems in testing, and even in production you'd probably want to log
> it somehow to help post mortem.
>
>
> Thanks,
> pq
Nobuhiko Tanibata
2014-03-15 05:41:51 UTC
Permalink
In-Vehicle Infotainment system traditionally manages surfaces with global
identification. A protocol, ivi_application, supports such a feature by
implementing a request, ivi_application::surface_creation defined in
ivi_application.xml. Additionally, it initialize a library, weston-layout,
to manage properties of surfaces and group surfaces in layer. In detail,
refer library, weston_layout.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- apply review comments of mailing list.
- squash update of Makefile into this patch.
- move this patch after patch of weston-layout.
- support inherit propoerties of id_surface when client attaches another
wl_surface with id_surface after destroying ivi_surface once.

ivi-shell/Makefile.am | 24 +++-
ivi-shell/ivi-shell.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 344 insertions(+), 1 deletion(-)
create mode 100644 ivi-shell/ivi-shell.c

diff --git a/ivi-shell/Makefile.am b/ivi-shell/Makefile.am
index 4d54c2d..d0c0d62 100644
--- a/ivi-shell/Makefile.am
+++ b/ivi-shell/Makefile.am
@@ -1,7 +1,8 @@
moduledir = $(libdir)/weston

module_LTLIBRARIES = \
- $(libweston_layout)
+ $(libweston_layout) \
+ $(ivi_shell)

AM_CPPFLAGS = \
-I$(top_srcdir)/shared \
@@ -17,6 +18,7 @@ westoninclude_HEADERS =

if ENABLE_IVI_SHELL
westoninclude_HEADERS += \
+ ivi-application-client-protocol.h \
weston-layout.h

libweston_layout = libweston-layout.la
@@ -27,4 +29,24 @@ libweston_layout_la_SOURCES = \
weston-layout.c \
weston-layout.h

+ivi_shell = ivi-shell.la
+ivi_shell_la_LDFLAGS = -module -avoid-version
+ivi_shell_la_LIBADD = $(COMPOSITOR_LIBS) $(IVI_SHELL_LIBS) ./libweston-layout.la
+ivi_shell_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) $(IVI_SHELL_CFLAGS)
+ivi_shell_la_SOURCES = \
+ ivi-shell.c \
+ weston-layout.h \
+ ivi-application-protocol.c \
+ ivi-application-server-protocol.h
+
endif
+
+BUILT_SOURCES = \
+ ivi-application-protocol.c \
+ ivi-application-server-protocol.h \
+ ivi-application-client-protocol.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
+wayland_protocoldir = $(top_srcdir)/protocol
+include $(top_srcdir)/wayland-scanner.mk
diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c
new file mode 100644
index 0000000..d5b1f2d
--- /dev/null
+++ b/ivi-shell/ivi-shell.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+/**
+ * ivi-shell supports a type of shell for In-Vehicle Infotainment system.
+ * In-Vehicle Infotainment system traditionally manages surfaces with global
+ * identification. A protocol, ivi_application, supports such a feature
+ * by implementing a request, ivi_application::surface_creation defined in
+ * ivi_application.xml.
+ *
+ * Additionally, it initialize a library, weston-layout, to manage properties of
+ * surfaces and group surfaces in layer. In detail, refer weston_layout.
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+
+#include "compositor.h"
+#include "ivi-application-server-protocol.h"
+#include "weston-layout.h"
+
+struct ivi_shell;
+
+struct ivi_shell_surface
+{
+ struct ivi_shell *shell;
+ struct weston_layout_surface *layout_surface;
+
+ struct weston_surface *surface;
+ uint32_t id_surface;
+
+ int32_t width;
+ int32_t height;
+
+ struct wl_list link;
+};
+
+struct ivi_shell
+{
+ struct wl_resource *resource;
+ struct wl_listener destroy_listener;
+
+ struct weston_compositor *compositor;
+
+ struct wl_list ivi_surface_list; /* struct ivi_shell_surface::link */
+};
+
+/* ------------------------------------------------------------------------- */
+/* common functions */
+/* ------------------------------------------------------------------------- */
+
+static void
+configure(struct weston_view *view, float x, float y)
+{
+ if (view != NULL) {
+ weston_view_set_position(view, x, y);
+ weston_view_update_transform(view);
+ }
+}
+
+/**
+ * Implementation of ivi_surface
+ */
+
+static void
+ivi_shell_surface_configure(struct weston_surface *, int32_t, int32_t);
+
+static struct ivi_shell_surface *
+get_ivi_shell_surface(struct weston_surface *surface)
+{
+ if (surface->configure == ivi_shell_surface_configure) {
+ return surface->configure_private;
+ } else {
+ return NULL;
+ }
+}
+
+static void
+ivi_shell_surface_configure(struct weston_surface *es,
+ int32_t sx, int32_t sy)
+{
+ struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(es);
+ struct weston_view *view = NULL;
+ float from_x = 0.0f;
+ float from_y = 0.0f;
+ float to_x = 0.0f;
+ float to_y = 0.0f;
+
+ if ((es->width == 0) || (es->height == 0) || (ivisurf == NULL)) {
+ return;
+ }
+
+ view = weston_layout_get_weston_view(ivisurf->layout_surface);
+ if (view == NULL) {
+ return;
+ }
+
+ if (ivisurf->width != es->width || ivisurf->height != es->height) {
+
+ ivisurf->width = es->width;
+ ivisurf->height = es->height;
+
+ weston_view_to_global_float(view, 0, 0, &from_x, &from_y);
+ weston_view_to_global_float(view, sx, sy, &to_x, &to_y);
+ configure(view,
+ view->geometry.x + to_x - from_x,
+ view->geometry.y + to_y - from_y);
+
+ weston_layout_surfaceConfigure(ivisurf->layout_surface, es->width, es->height);
+ }
+}
+
+static void
+surface_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ struct ivi_shell_surface *ivisurf = wl_resource_get_user_data(resource);
+
+ if (ivisurf != NULL) {
+ ivisurf->surface->configure = NULL;
+ ivisurf->surface->configure_private = NULL;
+ ivisurf->surface = NULL;
+ weston_layout_surfaceSetNativeContent(NULL, 0, 0, ivisurf->id_surface);
+ }
+
+ wl_resource_destroy(resource);
+}
+
+static const struct ivi_surface_interface surface_implementation = {
+ surface_destroy,
+};
+
+static struct ivi_shell_surface *
+is_surf_in_surfaces(struct wl_list *list_surf, uint32_t id_surface)
+{
+ struct ivi_shell_surface *ivisurf;
+
+ wl_list_for_each(ivisurf, list_surf, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+static const struct {
+ uint32_t warning_code; /* enum ivi_surface_warning_code */
+ const char *msg;
+} warning_strings[] = {
+ {IVI_SURFACE_WARNING_CODE_INVALID_WL_SURFACE, "wl_surface is invalid"},
+ {IVI_SURFACE_WARNING_CODE_SURFACE_ID_IN_USE, "surface_id is already assigned by another app"}
+};
+
+/**
+ * Implementation of ivi_application::surface_create.
+ * Creating new ivi_shell_surface with identification to identify the surface
+ * in the system.
+ */
+static void
+application_surface_create(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id_surface,
+ struct wl_resource *surface_resource,
+ uint32_t id)
+{
+ struct ivi_shell *shell = wl_resource_get_user_data(resource);
+ struct ivi_shell_surface *ivisurf = NULL;
+ struct weston_layout_surface *layout_surface = NULL;
+ struct weston_surface *es = wl_resource_get_user_data(surface_resource);
+ struct wl_resource *res;
+ int32_t warn_idx = -1;
+
+ if (es != NULL) {
+ layout_surface = weston_layout_surfaceCreate(es, id_surface);
+ if (layout_surface == NULL)
+ warn_idx = 1;
+ } else {
+ warn_idx = 0;
+ }
+
+ res = wl_resource_create(client, &ivi_surface_interface, 1, id);
+ if (res == NULL) {
+ weston_log("couldn't get surface object");
+ return;
+ }
+
+ if (warn_idx >= 0) {
+ wl_resource_set_implementation(res, &surface_implementation,
+ NULL, NULL);
+ ivi_surface_send_warning(res,
+ warning_strings[warn_idx].warning_code,
+ warning_strings[warn_idx].msg);
+ return;
+ }
+
+ ivisurf = is_surf_in_surfaces(&shell->ivi_surface_list, id_surface);
+ if (ivisurf == NULL) {
+ ivisurf = calloc(1, sizeof *ivisurf);
+ if (ivisurf == NULL) {
+ weston_log("fails to allocate memory\n");
+ return;
+ }
+
+ wl_list_init(&ivisurf->link);
+ wl_list_insert(&shell->ivi_surface_list, &ivisurf->link);
+
+ ivisurf->shell = shell;
+ ivisurf->id_surface = id_surface;
+ }
+
+ ivisurf->width = 0;
+ ivisurf->height = 0;
+ ivisurf->layout_surface = layout_surface;
+ ivisurf->surface = es;
+
+ es->configure = ivi_shell_surface_configure;
+ es->configure_private = ivisurf;
+
+ wl_resource_set_implementation(res, &surface_implementation,
+ ivisurf, NULL);
+}
+
+static const struct ivi_application_interface application_implementation = {
+ application_surface_create
+};
+
+static void
+bind_ivi_application(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct ivi_shell *shell = data;
+ struct wl_resource *resource = NULL;
+
+ resource = wl_resource_create(client, &ivi_application_interface, 1, id);
+
+ wl_resource_set_implementation(resource,
+ &application_implementation,
+ shell, NULL);
+}
+
+/**
+ * Initialization/destruction method of ivi-shell
+ */
+static void
+shell_destroy(struct wl_listener *listener, void *data)
+{
+ struct ivi_shell *shell =
+ container_of(listener, struct ivi_shell, destroy_listener);
+ struct ivi_shell_surface *ivisurf, *next;
+
+ wl_list_for_each_safe(ivisurf, next, &shell->ivi_surface_list, link) {
+ wl_list_remove(&ivisurf->link);
+ free(ivisurf);
+ }
+
+ free(shell);
+}
+
+static void
+init_ivi_shell(struct weston_compositor *ec, struct ivi_shell *shell)
+{
+ shell->compositor = ec;
+
+ wl_list_init(&ec->layer_list);
+ wl_list_init(&shell->ivi_surface_list);
+}
+
+/**
+ * Initialization of ivi-shell. A library, weston_layout, is also initialized
+ * here by calling weston_layout_initWithCompositor.
+ *
+ */
+
+WL_EXPORT int
+module_init(struct weston_compositor *ec,
+ int *argc, char *argv[])
+{
+ struct ivi_shell *shell = NULL;
+
+ shell = calloc(1, sizeof *shell);
+ if (shell == NULL) {
+ return -1;
+ }
+
+ init_ivi_shell(ec, shell);
+ weston_layout_initWithCompositor(ec);
+
+ shell->destroy_listener.notify = shell_destroy;
+ wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
+
+ if (wl_global_create(ec->wl_display, &ivi_application_interface, 1,
+ shell, bind_ivi_application) == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 09:57:58 UTC
Permalink
API set of controlling properties of surface and layer which groups
surfaces. An unique ID whose type is integer is required to create
surface and layer. With the unique ID, surface and layer are identified
to control them. The API set consists of APIs to control properties of
surface and layers about followings,

- visibility.
- opacity.
- clipping (x,y,width,height).
- position and size of it to be displayed.
- orientation per 90 degree.
- add or remove surfaces to a layer.
- order of surfaces/layers in layer/screen to be displayed.
- commit to apply property changes.
- notifications of property change.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
ivi-shell/weston-layout.c | 2633 +++++++++++++++++++++++++++++++++++++++++++++
ivi-shell/weston-layout.h | 920 ++++++++++++++++
2 files changed, 3553 insertions(+)
create mode 100644 ivi-shell/weston-layout.c
create mode 100644 ivi-shell/weston-layout.h

diff --git a/ivi-shell/weston-layout.c b/ivi-shell/weston-layout.c
new file mode 100644
index 0000000..0517e2d
--- /dev/null
+++ b/ivi-shell/weston-layout.c
@@ -0,0 +1,2633 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * Implementation of weston-layout library. The actual view on screen is
+ * not updated till calling weston_layout_commitChanges. A overview from
+ * calling API for updating properties of surfaces/layer to asking compositor
+ * to compose them by using weston_compositor_schedule_repaint,
+ * 0/ initialize this library by weston_layout_initWithCompositor
+ * with (struct weston_compositor *ec) from ivi-shell.
+ * 1/ When a API for updating properties of surface/layer, it updates
+ * pending prop of weston_layout_surface/layer/screen which are structure to
+ * store properties.
+ * 2/ Before calling commitChanges, in case of calling a API to get a property,
+ * return current property, not pending property.
+ * 3/ At the timing of calling weston_layout_commitChanges, pending properties
+ * are applied
+ * to properties.
+ * 4/ According properties, set transformation by using weston_matrix and
+ * weston_view per surfaces and layers in while loop.
+ * 5/ Set damage and trigger transform by using weston_view_geometry_dirty and
+ * weston_view_geometry_dirty.
+ * 6/ Notify update of properties.
+ * 7/ Trigger composition by weston_compositor_schedule_repaint.
+ *
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+#include <cairo.h>
+
+#include "compositor.h"
+#include "weston-layout.h"
+
+enum weston_layout_surface_orientation {
+ WESTON_LAYOUT_SURFACE_ORIENTATION_0_DEGREES = 0,
+ WESTON_LAYOUT_SURFACE_ORIENTATION_90_DEGREES = 1,
+ WESTON_LAYOUT_SURFACE_ORIENTATION_180_DEGREES = 2,
+ WESTON_LAYOUT_SURFACE_ORIENTATION_270_DEGREES = 3,
+};
+
+enum weston_layout_surface_pixelformat {
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_R_8 = 0,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGB_888 = 1,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_8888 = 2,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGB_565 = 3,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_5551 = 4,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_6661 = 5,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_4444 = 6,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_UNKNOWN = 7,
+};
+
+struct link_layer {
+ struct weston_layout_layer *ivilayer;
+ struct wl_list link;
+};
+
+struct link_screen {
+ struct weston_layout_screen *iviscrn;
+ struct wl_list link;
+};
+
+struct link_layerPropertyNotification {
+ layerPropertyNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfacePropertyNotification {
+ surfacePropertyNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_layerCreateNotification {
+ layerCreateNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_layerRemoveNotification {
+ layerRemoveNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceCreateNotification {
+ surfaceCreateNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceRemoveNotification {
+ surfaceRemoveNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceConfigureNotification {
+ surfaceConfigureNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct weston_layout;
+
+struct weston_layout_surface {
+ struct wl_list link;
+ struct wl_list list_notification;
+ struct wl_list list_layer;
+ uint32_t update_count;
+ uint32_t id_surface;
+
+ struct weston_layout *layout;
+ struct weston_surface *surface;
+ struct weston_view *view;
+
+ uint32_t buffer_width;
+ uint32_t buffer_height;
+
+ struct wl_listener surface_destroy_listener;
+ struct weston_transform surface_rotation;
+ struct weston_transform layer_rotation;
+ struct weston_transform surface_pos;
+ struct weston_transform layer_pos;
+ struct weston_transform scaling;
+ struct weston_layout_SurfaceProperties prop;
+ int32_t pixelformat;
+ uint32_t event_mask;
+
+ struct {
+ struct weston_layout_SurfaceProperties prop;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list link;
+ struct wl_list list_layer;
+ } order;
+};
+
+struct weston_layout_layer {
+ struct wl_list link;
+ struct wl_list list_notification;
+ struct wl_list list_screen;
+ uint32_t id_layer;
+
+ struct weston_layout *layout;
+ struct weston_layer el;
+
+ struct weston_layout_LayerProperties prop;
+ uint32_t event_mask;
+
+ struct {
+ struct weston_layout_LayerProperties prop;
+ struct wl_list list_surface;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list list_surface;
+ struct wl_list link;
+ } order;
+};
+
+struct weston_layout_screen {
+ struct wl_list link;
+ uint32_t id_screen;
+
+ struct weston_layout *layout;
+ struct weston_output *output;
+
+ uint32_t event_mask;
+
+ struct {
+ struct wl_list list_layer;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list list_layer;
+ struct wl_list link;
+ } order;
+};
+
+struct weston_layout {
+ struct weston_compositor *compositor;
+
+ struct wl_list list_surface;
+ struct wl_list list_layer;
+ struct wl_list list_screen;
+
+ struct {
+ struct wl_list list_create;
+ struct wl_list list_remove;
+ } layer_notification;
+
+ struct {
+ struct wl_list list_create;
+ struct wl_list list_remove;
+ struct wl_list list_configure;
+ } surface_notification;
+
+ /* to enalbe displaying cursor*/
+ int32_t is_cursor_enabled;
+};
+
+struct weston_layout ivilayout = {0};
+
+static struct weston_layout *
+get_instance(void)
+{
+ return &ivilayout;
+}
+
+/**
+ * Internal API to add/remove a surface from layer.
+ */
+static void
+add_ordersurface_to_layer(struct weston_layout_surface *ivisurf,
+ struct weston_layout_layer *ivilayer)
+{
+ struct link_layer *link_layer = NULL;
+
+ link_layer = malloc(sizeof *link_layer);
+ if (link_layer == NULL) {
+ weston_log("fails to allocate memory\n");
+ return;
+ }
+
+ link_layer->ivilayer = ivilayer;
+ wl_list_init(&link_layer->link);
+ wl_list_insert(&ivisurf->list_layer, &link_layer->link);
+}
+
+static void
+remove_ordersurface_from_layer(struct weston_layout_surface *ivisurf)
+{
+ struct link_layer *link_layer = NULL;
+ struct link_layer *next = NULL;
+
+ wl_list_for_each_safe(link_layer, next, &ivisurf->list_layer, link) {
+ if (!wl_list_empty(&link_layer->link)) {
+ wl_list_remove(&link_layer->link);
+ }
+ free(link_layer);
+ link_layer = NULL;
+ }
+ wl_list_init(&ivisurf->list_layer);
+}
+
+/**
+ * Internal API to add/remove a layer from screen.
+ */
+static void
+add_orderlayer_to_screen(struct weston_layout_layer *ivilayer,
+ struct weston_layout_screen *iviscrn)
+{
+ struct link_screen *link_scrn = NULL;
+
+ link_scrn = malloc(sizeof *link_scrn);
+ if (link_scrn == NULL) {
+ weston_log("fails to allocate memory\n");
+ return;
+ }
+
+ link_scrn->iviscrn = iviscrn;
+ wl_list_init(&link_scrn->link);
+ wl_list_insert(&ivilayer->list_screen, &link_scrn->link);
+}
+
+static void
+remove_orderlayer_from_screen(struct weston_layout_layer *ivilayer)
+{
+ struct link_screen *link_scrn = NULL;
+ struct link_screen *next = NULL;
+
+ wl_list_for_each_safe(link_scrn, next, &ivilayer->list_screen, link) {
+ if (!wl_list_empty(&link_scrn->link)) {
+ wl_list_remove(&link_scrn->link);
+ }
+ free(link_scrn);
+ link_scrn = NULL;
+ }
+ wl_list_init(&ivilayer->list_screen);
+}
+
+/**
+ * Internal API to add/remove a layer from screen.
+ */
+static struct weston_layout_surface *
+get_surface(struct wl_list *list_surf, uint32_t id_surface)
+{
+ struct weston_layout_surface *ivisurf;
+
+ wl_list_for_each(ivisurf, list_surf, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+static struct weston_layout_layer *
+get_layer(struct wl_list *list_layer, uint32_t id_layer)
+{
+ struct weston_layout_layer *ivilayer;
+
+ wl_list_for_each(ivilayer, list_layer, link) {
+ if (ivilayer->id_layer == id_layer) {
+ return ivilayer;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Called at destruction of ivi_surface
+ */
+static void
+westonsurface_destroy_from_ivisurface(struct wl_listener *listener, void *data)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+
+ ivisurf = container_of(listener, struct weston_layout_surface,
+ surface_destroy_listener);
+ ivisurf->surface = NULL;
+}
+
+/**
+ * Internal API to check layer/surface already added in layer/screen.
+ * Called by weston_layout_layerAddSurface/weston_layout_screenAddLayer
+ */
+static int
+is_surface_in_layer(struct weston_layout_surface *ivisurf,
+ struct weston_layout_layer *ivilayer)
+{
+ struct weston_layout_surface *surf = NULL;
+
+ wl_list_for_each(surf, &ivilayer->pending.list_surface, pending.link) {
+ if (surf->id_surface == ivisurf->id_surface) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+is_layer_in_screen(struct weston_layout_layer *ivilayer,
+ struct weston_layout_screen *iviscrn)
+{
+ struct weston_layout_layer *layer = NULL;
+
+ wl_list_for_each(layer, &iviscrn->pending.list_layer, pending.link) {
+ if (layer->id_layer == ivilayer->id_layer) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Internal API to initialize screens found from output_list of weston_compositor.
+ * Called by weston_layout_initWithCompositor.
+ */
+static void
+create_screen(struct weston_compositor *ec)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_screen *iviscrn = NULL;
+ struct weston_output *output = NULL;
+ int32_t count = 0;
+
+ wl_list_for_each(output, &ec->output_list, link) {
+ iviscrn = calloc(1, sizeof *iviscrn);
+ if (iviscrn == NULL) {
+ weston_log("fails to allocate memory\n");
+ continue;
+ }
+
+ wl_list_init(&iviscrn->link);
+ iviscrn->layout = layout;
+
+ iviscrn->id_screen = count;
+ count++;
+
+ iviscrn->output = output;
+ iviscrn->event_mask = 0;
+
+ wl_list_init(&iviscrn->pending.list_layer);
+ wl_list_init(&iviscrn->pending.link);
+
+ wl_list_init(&iviscrn->order.list_layer);
+ wl_list_init(&iviscrn->order.link);
+
+ wl_list_insert(&layout->list_screen, &iviscrn->link);
+ }
+}
+
+/**
+ * Internal APIs to initialize properties of surface/layer when they are created.
+ */
+static void
+init_layerProperties(struct weston_layout_LayerProperties *prop,
+ int32_t width, int32_t height)
+{
+ memset(prop, 0, sizeof *prop);
+ prop->opacity = wl_fixed_from_double(1.0);
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+ prop->destWidth = width;
+ prop->destHeight = height;
+}
+
+static void
+init_surfaceProperties(struct weston_layout_SurfaceProperties *prop)
+{
+ memset(prop, 0, sizeof *prop);
+ prop->opacity = wl_fixed_from_double(1.0);
+}
+
+/**
+ * Internal APIs to be called from weston_layout_commitChanges.
+ */
+static void
+update_opacity(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ double layer_alpha = wl_fixed_to_double(ivilayer->prop.opacity);
+ double surf_alpha = wl_fixed_to_double(ivisurf->prop.opacity);
+
+ if ((ivilayer->event_mask & IVI_NOTIFICATION_OPACITY) ||
+ (ivisurf->event_mask & IVI_NOTIFICATION_OPACITY)) {
+ if (ivisurf->view == NULL) {
+ return;
+ }
+ ivisurf->view->alpha = layer_alpha * surf_alpha;
+ }
+}
+
+static void
+update_surface_orientation(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->surface_rotation.matrix;
+ float width = 0.0f;
+ float height = 0.0f;
+ float v_sin = 0.0f;
+ float v_cos = 0.0f;
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float sx = 1.0f;
+ float sy = 1.0f;
+
+ if (view == NULL) {
+ return;
+ }
+
+ if ((ivilayer->prop.destWidth == 0) ||
+ (ivilayer->prop.destHeight == 0)) {
+ return;
+ }
+ width = (float)ivilayer->prop.destWidth;
+ height = (float)ivilayer->prop.destHeight;
+
+ switch (ivisurf->prop.orientation) {
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_0_DEGREES:
+ v_sin = 0.0f;
+ v_cos = 1.0f;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_90_DEGREES:
+ v_sin = 1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_180_DEGREES:
+ v_sin = 0.0f;
+ v_cos = -1.0f;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_270_DEGREES:
+ default:
+ v_sin = -1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ }
+ wl_list_remove(&ivisurf->surface_rotation.link);
+ weston_view_geometry_dirty(view);
+
+ weston_matrix_init(matrix);
+ cx = 0.5f * width;
+ cy = 0.5f * height;
+ weston_matrix_translate(matrix, -cx, -cy, 0.0f);
+ weston_matrix_rotate_xy(matrix, v_cos, v_sin);
+ weston_matrix_scale(matrix, sx, sy, 1.0);
+ weston_matrix_translate(matrix, cx, cy, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->surface_rotation.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_layer_orientation(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_surface *es = ivisurf->surface;
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->layer_rotation.matrix;
+ struct weston_output *output = NULL;
+ float width = 0.0f;
+ float height = 0.0f;
+ float v_sin = 0.0f;
+ float v_cos = 0.0f;
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float sx = 1.0f;
+ float sy = 1.0f;
+
+ if (es == NULL || view == NULL) {
+ return;
+ }
+
+ output = es->output;
+ if (output == NULL) {
+ return;
+ }
+ if ((output->width == 0) || (output->height == 0)) {
+ return;
+ }
+ width = (float)output->width;
+ height = (float)output->height;
+
+ switch (ivilayer->prop.orientation) {
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_0_DEGREES:
+ v_sin = 0.0f;
+ v_cos = 1.0f;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_90_DEGREES:
+ v_sin = 1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_180_DEGREES:
+ v_sin = 0.0f;
+ v_cos = -1.0f;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_270_DEGREES:
+ default:
+ v_sin = -1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ }
+ wl_list_remove(&ivisurf->layer_rotation.link);
+ weston_view_geometry_dirty(view);
+
+ weston_matrix_init(matrix);
+ cx = 0.5f * width;
+ cy = 0.5f * height;
+ weston_matrix_translate(matrix, -cx, -cy, 0.0f);
+ weston_matrix_rotate_xy(matrix, v_cos, v_sin);
+ weston_matrix_scale(matrix, sx, sy, 1.0);
+ weston_matrix_translate(matrix, cx, cy, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->layer_rotation.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_surface_position(struct weston_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ float tx = (float)ivisurf->prop.destX;
+ float ty = (float)ivisurf->prop.destY;
+ struct weston_matrix *matrix = &ivisurf->surface_pos.matrix;
+
+ if (view == NULL) {
+ return;
+ }
+
+ wl_list_remove(&ivisurf->surface_pos.link);
+
+ weston_matrix_init(matrix);
+ weston_matrix_translate(matrix, tx, ty, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->surface_pos.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+
+#if 0
+ /* disable zoom animation */
+ weston_zoom_run(es, 0.0, 1.0, NULL, NULL);
+#endif
+
+}
+
+static void
+update_layer_position(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->layer_pos.matrix;
+ float tx = (float)ivilayer->prop.destX;
+ float ty = (float)ivilayer->prop.destY;
+
+ if (view == NULL) {
+ return;
+ }
+
+ wl_list_remove(&ivisurf->layer_pos.link);
+
+ weston_matrix_init(matrix);
+ weston_matrix_translate(matrix, tx, ty, 0.0f);
+ wl_list_insert(
+ &view->geometry.transformation_list,
+ &ivisurf->layer_pos.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_scale(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->scaling.matrix;
+ float sx = 0.0f;
+ float sy = 0.0f;
+ float lw = 0.0f;
+ float sw = 0.0f;
+ float lh = 0.0f;
+ float sh = 0.0f;
+
+ if (view == NULL) {
+ return;
+ }
+
+ if (ivisurf->prop.sourceWidth == 0 && ivisurf->prop.sourceHeight == 0) {
+ ivisurf->prop.sourceWidth = ivisurf->buffer_width;
+ ivisurf->prop.sourceHeight = ivisurf->buffer_height;
+
+ if (ivisurf->prop.destWidth == 0 && ivisurf->prop.destHeight == 0) {
+ ivisurf->prop.destWidth = ivisurf->buffer_width;
+ ivisurf->prop.destHeight = ivisurf->buffer_height;
+ }
+ }
+
+ lw = ((float)ivilayer->prop.destWidth / ivilayer->prop.sourceWidth );
+ sw = ((float)ivisurf->prop.destWidth / ivisurf->prop.sourceWidth );
+ lh = ((float)ivilayer->prop.destHeight / ivilayer->prop.sourceHeight);
+ sh = ((float)ivisurf->prop.destHeight / ivisurf->prop.sourceHeight );
+ sx = sw * lw;
+ sy = sh * lh;
+
+ wl_list_remove(&ivisurf->scaling.link);
+ weston_matrix_init(matrix);
+ weston_matrix_scale(matrix, sx, sy, 1.0f);
+
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->scaling.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_prop(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ if (ivilayer->event_mask | ivisurf->event_mask) {
+ update_opacity(ivilayer, ivisurf);
+ update_layer_orientation(ivilayer, ivisurf);
+ update_layer_position(ivilayer, ivisurf);
+ update_surface_position(ivisurf);
+ update_surface_orientation(ivilayer, ivisurf);
+ update_scale(ivilayer, ivisurf);
+
+ ivisurf->update_count++;
+
+ if (ivisurf->view != NULL) {
+ weston_view_geometry_dirty(ivisurf->view);
+ }
+
+ if (ivisurf->surface != NULL) {
+ weston_surface_damage(ivisurf->surface);
+ }
+ }
+}
+
+static void
+commit_changes(struct weston_layout *layout)
+{
+ struct weston_layout_screen *iviscrn = NULL;
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, order.link) {
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, order.link) {
+ update_prop(ivilayer, ivisurf);
+ }
+ }
+ }
+}
+
+static void
+commit_list_surface(struct weston_layout *layout)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ ivisurf->prop = ivisurf->pending.prop;
+ }
+}
+
+static void
+commit_list_layer(struct weston_layout *layout)
+{
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_surface *next = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ ivilayer->prop = ivilayer->pending.prop;
+
+ if (!(ivilayer->event_mask & IVI_NOTIFICATION_ADD)) {
+ continue;
+ }
+
+ wl_list_for_each_safe(ivisurf, next,
+ &ivilayer->order.list_surface, order.link) {
+ remove_ordersurface_from_layer(ivisurf);
+
+ if (!wl_list_empty(&ivisurf->order.link)) {
+ wl_list_remove(&ivisurf->order.link);
+ }
+
+ wl_list_init(&ivisurf->order.link);
+ }
+
+ wl_list_init(&ivilayer->order.list_surface);
+ wl_list_for_each(ivisurf, &ivilayer->pending.list_surface,
+ pending.link) {
+ wl_list_insert(&ivilayer->order.list_surface,
+ &ivisurf->order.link);
+ add_ordersurface_to_layer(ivisurf, ivilayer);
+ }
+ }
+}
+
+static void
+commit_list_screen(struct weston_layout *layout)
+{
+ struct weston_compositor *ec = layout->compositor;
+ struct weston_layout_screen *iviscrn = NULL;
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_layer *next = NULL;
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ if (iviscrn->event_mask & IVI_NOTIFICATION_ADD) {
+ wl_list_for_each_safe(ivilayer, next,
+ &iviscrn->order.list_layer, order.link) {
+ remove_orderlayer_from_screen(ivilayer);
+
+ if (!wl_list_empty(&ivilayer->order.link)) {
+ wl_list_remove(&ivilayer->order.link);
+ }
+
+ wl_list_init(&ivilayer->order.link);
+ }
+
+ wl_list_init(&iviscrn->order.list_layer);
+ wl_list_for_each(ivilayer, &iviscrn->pending.list_layer,
+ pending.link) {
+ wl_list_insert(&iviscrn->order.list_layer,
+ &ivilayer->order.link);
+ add_orderlayer_to_screen(ivilayer, iviscrn);
+ }
+ iviscrn->event_mask = 0;
+ }
+
+ /* For rendering */
+ wl_list_init(&ec->layer_list);
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, order.link) {
+ if (ivilayer->prop.visibility == 0) {
+ continue;
+ }
+
+ wl_list_insert(&ec->layer_list, &ivilayer->el.link);
+ wl_list_init(&ivilayer->el.view_list);
+
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, order.link) {
+ if (ivisurf->prop.visibility == 0) {
+ continue;
+ }
+
+ if (ivisurf->surface == NULL || ivisurf->view == NULL) {
+ continue;
+ }
+
+ wl_list_insert(&ivilayer->el.view_list,
+ &ivisurf->view->layer_link);
+ ivisurf->surface->output = iviscrn->output;
+ }
+ }
+
+ /*Add cursor layer if cursor is configured.*/
+ if (layout->is_cursor_enabled) {
+ wl_list_insert(&ec->layer_list, &ec->cursor_layer.link);
+ }
+
+ break;
+ }
+}
+
+static void
+send_surface_prop(struct weston_layout_surface *ivisurf)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+
+ wl_list_for_each(notification, &ivisurf->list_notification, link) {
+ notification->callback(ivisurf, &ivisurf->prop,
+ ivisurf->event_mask,
+ notification->userdata);
+ }
+
+ ivisurf->event_mask = 0;
+}
+
+static void
+send_layer_prop(struct weston_layout_layer *ivilayer)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+
+ wl_list_for_each(notification, &ivilayer->list_notification, link) {
+ notification->callback(ivilayer, &ivilayer->prop,
+ ivilayer->event_mask,
+ notification->userdata);
+ }
+
+ ivilayer->event_mask = 0;
+}
+
+static void
+send_prop(struct weston_layout *layout)
+{
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ send_layer_prop(ivilayer);
+ }
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ send_surface_prop(ivisurf);
+ }
+}
+
+/**
+ * Exported APIs of weston-layout library are implemented from here.
+ * Brief of APIs is described in weston-layout.h.
+ */
+WL_EXPORT struct weston_view *
+weston_layout_get_weston_view(struct weston_layout_surface *surface)
+{
+ return (surface != NULL) ? surface->view : NULL;
+}
+
+WL_EXPORT void
+weston_layout_initWithCompositor(struct weston_compositor *ec)
+{
+ struct weston_layout *layout = get_instance();
+
+ layout->compositor = ec;
+
+ wl_list_init(&layout->list_surface);
+ wl_list_init(&layout->list_layer);
+ wl_list_init(&layout->list_screen);
+
+ wl_list_init(&layout->layer_notification.list_create);
+ wl_list_init(&layout->layer_notification.list_remove);
+
+ wl_list_init(&layout->surface_notification.list_create);
+ wl_list_init(&layout->surface_notification.list_remove);
+ wl_list_init(&layout->surface_notification.list_configure);
+
+ create_screen(ec);
+
+ struct weston_config *config = weston_config_parse("weston.ini");
+ struct weston_config_section *s =
+ weston_config_get_section(config, "ivi-shell", NULL, NULL);
+
+ /*A cursor is configured if weston.ini has keys.*/
+ char* cursor_theme = NULL;
+ weston_config_section_get_string(s, "cursor-theme", &cursor_theme, NULL);
+ layout->is_cursor_enabled = (NULL != cursor_theme);
+ free(cursor_theme);
+ weston_config_destroy(config);
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationCreateLayer(layerCreateNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_layerCreateNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationCreateLayer: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->layer_notification.list_create, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationRemoveLayer(layerRemoveNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_layerRemoveNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationRemoveLayer: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->layer_notification.list_remove, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationCreateSurface(surfaceCreateNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationCreateSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_create, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationRemoveSurface(surfaceRemoveNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceRemoveNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationRemoveSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_remove, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationConfigureSurface(surfaceConfigureNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceConfigureNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationConfigureSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_configure, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT uint32_t
+weston_layout_getIdOfSurface(struct weston_layout_surface *ivisurf)
+{
+ return ivisurf->id_surface;
+}
+
+WL_EXPORT uint32_t
+weston_layout_getIdOfLayer(struct weston_layout_layer *ivilayer)
+{
+ return ivilayer->id_layer;
+}
+
+WL_EXPORT struct weston_layout_layer *
+weston_layout_getLayerFromId(uint32_t id_layer)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ if (ivilayer->id_layer == id_layer) {
+ return ivilayer;
+ }
+ }
+
+ return NULL;
+}
+
+WL_EXPORT struct weston_layout_surface *
+weston_layout_getSurfaceFromId(uint32_t id_surface)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+WL_EXPORT struct weston_layout_screen *
+weston_layout_getScreenFromId(uint32_t id_screen)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_screen *iviscrn = NULL;
+ (void)id_screen;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+//FIXME : select iviscrn from list_screen by id_screen
+ return iviscrn;
+ break;
+ }
+
+ return NULL;
+}
+
+WL_EXPORT int32_t
+weston_layout_getScreenResolution(struct weston_layout_screen *iviscrn,
+ uint32_t *pWidth, uint32_t *pHeight)
+{
+ struct weston_output *output = NULL;
+
+ if (pWidth == NULL || pHeight == NULL) {
+ weston_log("weston_layout_getScreenResolution: invalid argument\n");
+ return -1;
+ }
+
+ output = iviscrn->output;
+ *pWidth = output->current_mode->width;
+ *pHeight = output->current_mode->height;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceAddNotification(struct weston_layout_surface *ivisurf,
+ surfacePropertyNotificationFunc callback,
+ void *userdata)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+
+ if (ivisurf == NULL || callback == NULL) {
+ weston_log("weston_layout_surfaceAddNotification: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&ivisurf->list_notification, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceRemoveNotification(struct weston_layout_surface *ivisurf)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+ struct link_surfacePropertyNotification *next = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceRemoveNotification: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(notification, next,
+ &ivisurf->list_notification, link) {
+ if (!wl_list_empty(&notification->link)) {
+ wl_list_remove(&notification->link);
+ }
+ free(notification);
+ notification = NULL;
+ }
+ wl_list_init(&ivisurf->list_notification);
+
+ return 0;
+}
+
+WL_EXPORT struct weston_layout_surface*
+weston_layout_surfaceCreate(struct weston_surface *wl_surface,
+ uint32_t id_surface)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ if (wl_surface == NULL) {
+ weston_log("weston_layout_surfaceCreate: invalid argument\n");
+ return NULL;
+ }
+
+ ivisurf = get_surface(&layout->list_surface, id_surface);
+ if (ivisurf != NULL) {
+//FIXME
+ weston_log("id_surface is already created\n");
+ ivisurf->surface = wl_surface;
+ if (wl_surface != NULL) {
+ ivisurf->surface_destroy_listener.notify =
+ westonsurface_destroy_from_ivisurface;
+ wl_resource_add_destroy_listener(wl_surface->resource,
+ &ivisurf->surface_destroy_listener);
+
+ }
+
+ if (ivisurf->view != NULL) {
+ weston_view_destroy(ivisurf->view);
+ }
+ ivisurf->view = NULL;
+
+ if (wl_surface != NULL) {
+ ivisurf->view = weston_view_create(wl_surface);
+ if (ivisurf->view == NULL) {
+ weston_log("fails to allocate memory\n");
+ }
+ }
+
+ ivisurf->buffer_width = 0;
+ ivisurf->buffer_height = 0;
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ return NULL;
+ }
+
+ ivisurf = calloc(1, sizeof *ivisurf);
+ if (ivisurf == NULL) {
+ weston_log("fails to allocate memory\n");
+ return NULL;
+ }
+
+ wl_list_init(&ivisurf->link);
+ wl_list_init(&ivisurf->list_notification);
+ wl_list_init(&ivisurf->list_layer);
+ ivisurf->id_surface = id_surface;
+ ivisurf->layout = layout;
+
+ ivisurf->surface = wl_surface;
+ if (wl_surface != NULL) {
+ ivisurf->surface_destroy_listener.notify =
+ westonsurface_destroy_from_ivisurface;
+ wl_resource_add_destroy_listener(wl_surface->resource,
+ &ivisurf->surface_destroy_listener);
+
+ ivisurf->view = weston_view_create(wl_surface);
+ if (ivisurf->view == NULL) {
+ weston_log("fails to allocate memory\n");
+ }
+ }
+
+ ivisurf->buffer_width = 0;
+ ivisurf->buffer_height = 0;
+
+ wl_list_init(&ivisurf->surface_rotation.link);
+ wl_list_init(&ivisurf->layer_rotation.link);
+ wl_list_init(&ivisurf->surface_pos.link);
+ wl_list_init(&ivisurf->layer_pos.link);
+ wl_list_init(&ivisurf->scaling.link);
+
+ init_surfaceProperties(&ivisurf->prop);
+ ivisurf->pixelformat = WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_8888;
+ ivisurf->event_mask = 0;
+
+ ivisurf->pending.prop = ivisurf->prop;
+ wl_list_init(&ivisurf->pending.link);
+
+ wl_list_init(&ivisurf->order.link);
+ wl_list_init(&ivisurf->order.list_layer);
+
+ wl_list_insert(&layout->list_surface, &ivisurf->link);
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ return ivisurf;
+}
+
+WL_EXPORT void
+weston_layout_surfaceConfigure(struct weston_layout_surface *ivisurf,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ ivisurf->buffer_width = width;
+ ivisurf->buffer_height = height;
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_configure, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceRemove(struct weston_layout_surface *ivisurf)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceRemoveNotification *notification = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceRemove: invalid argument\n");
+ return -1;
+ }
+
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ if (!wl_list_empty(&ivisurf->order.link)) {
+ wl_list_remove(&ivisurf->order.link);
+ }
+ if (!wl_list_empty(&ivisurf->link)) {
+ wl_list_remove(&ivisurf->link);
+ }
+ remove_ordersurface_from_layer(ivisurf);
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_remove, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ if (ivisurf->view != NULL) {
+ weston_view_destroy(ivisurf->view);
+ }
+
+ free(ivisurf);
+ ivisurf = NULL;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_UpdateInputEventAcceptanceOn(struct weston_layout_surface *ivisurf,
+ uint32_t devices, uint32_t acceptance)
+{
+ /* not supported */
+ (void)ivisurf;
+ (void)devices;
+ (void)acceptance;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceInitialize(struct weston_layout_surface **pSurfaceId)
+{
+ /* not supported */
+ (void)pSurfaceId;
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getPropertiesOfLayer(struct weston_layout_layer *ivilayer,
+ struct weston_layout_LayerProperties *pLayerProperties)
+{
+ if (ivilayer == NULL || pLayerProperties == NULL) {
+ weston_log("weston_layout_getPropertiesOfLayer: invalid argument\n");
+ return -1;
+ }
+
+ *pLayerProperties = ivilayer->prop;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getNumberOfHardwareLayers(uint32_t id_screen,
+ uint32_t *pNumberOfHardwareLayers)
+{
+ /* not supported */
+ (void)id_screen;
+ (void)pNumberOfHardwareLayers;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getScreens(uint32_t *pLength, weston_layout_screen_ptr **ppArray)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_screen *iviscrn = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getScreens: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_screen);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_screen_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ (*ppArray)[n++] = iviscrn;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getScreensUnderLayer(struct weston_layout_layer *ivilayer,
+ uint32_t *pLength,
+ weston_layout_screen_ptr **ppArray)
+{
+ struct link_screen *link_scrn = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getScreensUnderLayer: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivilayer->list_screen);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_screen_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(link_scrn, &ivilayer->list_screen, link) {
+ (*ppArray)[n++] = link_scrn->iviscrn;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getLayers(uint32_t *pLength, weston_layout_layer_ptr **ppArray)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getLayers: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ (*ppArray)[n++] = ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getLayersOnScreen(struct weston_layout_screen *iviscrn,
+ uint32_t *pLength,
+ weston_layout_layer_ptr **ppArray)
+{
+ struct weston_layout_layer *ivilayer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (iviscrn == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getLayersOnScreen: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&iviscrn->order.list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, link) {
+ (*ppArray)[n++] = ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getLayersUnderSurface(struct weston_layout_surface *ivisurf,
+ uint32_t *pLength,
+ weston_layout_layer_ptr **ppArray)
+{
+ struct link_layer *link_layer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivisurf == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getLayers: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivisurf->list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(link_layer, &ivisurf->list_layer, link) {
+ (*ppArray)[n++] = link_layer->ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getSurfaces(uint32_t *pLength, weston_layout_surface_ptr **ppArray)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getSurfaces: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_surface);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_surface_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ (*ppArray)[n++] = ivisurf;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getSurfacesOnLayer(struct weston_layout_layer *ivilayer,
+ uint32_t *pLength,
+ weston_layout_surface_ptr **ppArray)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getSurfaceIDsOnLayer: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivilayer->order.list_surface);
+
+ if (length != 0) {
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_surface_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, link) {
+ (*ppArray)[n++] = ivisurf;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT struct weston_layout_layer *
+weston_layout_layerCreateWithDimension(uint32_t id_layer,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+ struct link_layerCreateNotification *notification = NULL;
+
+ ivilayer = get_layer(&layout->list_layer, id_layer);
+ if (ivilayer != NULL) {
+ weston_log("id_layer is already created\n");
+ return ivilayer;
+ }
+
+ ivilayer = calloc(1, sizeof *ivilayer);
+ if (ivilayer == NULL) {
+ weston_log("fails to allocate memory\n");
+ return NULL;
+ }
+
+ wl_list_init(&ivilayer->link);
+ wl_list_init(&ivilayer->list_notification);
+ wl_list_init(&ivilayer->list_screen);
+ ivilayer->layout = layout;
+ ivilayer->id_layer = id_layer;
+
+ init_layerProperties(&ivilayer->prop, width, height);
+ ivilayer->event_mask = 0;
+
+ wl_list_init(&ivilayer->pending.list_surface);
+ wl_list_init(&ivilayer->pending.link);
+ ivilayer->pending.prop = ivilayer->prop;
+
+ wl_list_init(&ivilayer->order.list_surface);
+ wl_list_init(&ivilayer->order.link);
+
+ wl_list_insert(&layout->list_layer, &ivilayer->link);
+
+ wl_list_for_each(notification,
+ &layout->layer_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivilayer, notification->userdata);
+ }
+ }
+
+ return ivilayer;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerRemove(struct weston_layout_layer *ivilayer)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_layerRemoveNotification *notification = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerRemove: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each(notification,
+ &layout->layer_notification.list_remove, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivilayer, notification->userdata);
+ }
+ }
+
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ if (!wl_list_empty(&ivilayer->order.link)) {
+ wl_list_remove(&ivilayer->order.link);
+ }
+ if (!wl_list_empty(&ivilayer->link)) {
+ wl_list_remove(&ivilayer->link);
+ }
+ remove_orderlayer_from_screen(ivilayer);
+
+ free(ivilayer);
+ ivilayer = NULL;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetType(struct weston_layout_layer *ivilayer,
+ uint32_t *pLayerType)
+{
+ /* not supported */
+ (void)ivilayer;
+ (void)pLayerType;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetVisibility(struct weston_layout_layer *ivilayer,
+ uint32_t newVisibility)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->visibility = newVisibility;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_VISIBILITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetVisibility(struct weston_layout_layer *ivilayer, uint32_t *pVisibility)
+{
+ if (ivilayer == NULL || pVisibility == NULL) {
+ weston_log("weston_layout_layerGetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ *pVisibility = ivilayer->prop.visibility;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetOpacity(struct weston_layout_layer *ivilayer,
+ float opacity)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->opacity = opacity;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_OPACITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetOpacity(struct weston_layout_layer *ivilayer,
+ float *pOpacity)
+{
+ if (ivilayer == NULL || pOpacity == NULL) {
+ weston_log("weston_layout_layerGetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ *pOpacity = ivilayer->prop.opacity;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetSourceRectangle(struct weston_layout_layer *ivilayer,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetSourceRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->sourceX = x;
+ prop->sourceY = y;
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetDestinationRectangle(struct weston_layout_layer *ivilayer,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetDestinationRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->destX = x;
+ prop->destY = y;
+ prop->destWidth = width;
+ prop->destHeight = height;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_DEST_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetDimension(struct weston_layout_layer *ivilayer,
+ uint32_t *pDimension)
+{
+ if (ivilayer == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("weston_layout_layerGetDimension: invalid argument\n");
+ return -1;
+ }
+
+ pDimension[0] = ivilayer->prop.destX;
+ pDimension[1] = ivilayer->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetDimension(struct weston_layout_layer *ivilayer,
+ uint32_t *pDimension)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("weston_layout_layerSetDimension: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+
+ prop->destWidth = pDimension[0];
+ prop->destHeight = pDimension[1];
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_DIMENSION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetPosition(struct weston_layout_layer *ivilayer, int32_t *pPosition)
+{
+ if (ivilayer == NULL || pPosition == NULL) {
+ weston_log("weston_layout_layerGetPosition: invalid argument\n");
+ return -1;
+ }
+
+ pPosition[0] = ivilayer->prop.destX;
+ pPosition[1] = ivilayer->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetPosition(struct weston_layout_layer *ivilayer, int32_t *pPosition)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL || pPosition == NULL) {
+ weston_log("weston_layout_layerSetPosition: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->destX = pPosition[0];
+ prop->destY = pPosition[1];
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_POSITION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetOrientation(struct weston_layout_layer *ivilayer,
+ uint32_t orientation)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->orientation = orientation;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ORIENTATION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetOrientation(struct weston_layout_layer *ivilayer,
+ uint32_t *pOrientation)
+{
+ if (ivilayer == NULL || pOrientation == NULL) {
+ weston_log("weston_layout_layerGetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ *pOrientation = ivilayer->prop.orientation;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetChromaKey(struct weston_layout_layer *ivilayer, uint32_t* pColor)
+{
+ /* not supported */
+ (void)ivilayer;
+ (void)pColor;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetRenderOrder(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface **pSurface,
+ uint32_t number)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+ uint32_t *id_surface = NULL;
+ uint32_t i = 0;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetRenderOrder: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_init(&ivilayer->pending.list_surface);
+
+ if (pSurface == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < number; i++) {
+ id_surface = &pSurface[i]->id_surface;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ if (*id_surface != ivisurf->id_surface) {
+ continue;
+ }
+
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ wl_list_insert(&ivilayer->pending.list_surface,
+ &ivisurf->pending.link);
+ break;
+ }
+ }
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetCapabilities(struct weston_layout_layer *ivilayer,
+ uint32_t *pCapabilities)
+{
+ /* not supported */
+ (void)ivilayer;
+ (void)pCapabilities;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerTypeGetCapabilities(uint32_t layerType,
+ uint32_t *pCapabilities)
+{
+ /* not supported */
+ (void)layerType;
+ (void)pCapabilities;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetVisibility(struct weston_layout_surface *ivisurf,
+ uint32_t newVisibility)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->visibility = newVisibility;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_VISIBILITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetVisibility(struct weston_layout_surface *ivisurf,
+ uint32_t *pVisibility)
+{
+ if (ivisurf == NULL || pVisibility == NULL) {
+ weston_log("weston_layout_surfaceGetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ *pVisibility = ivisurf->prop.visibility;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetOpacity(struct weston_layout_surface *ivisurf,
+ float opacity)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->opacity = opacity;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_OPACITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetOpacity(struct weston_layout_surface *ivisurf,
+ float *pOpacity)
+{
+ if (ivisurf == NULL || pOpacity == NULL) {
+ weston_log("weston_layout_surfaceGetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ *pOpacity = ivisurf->prop.opacity;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_SetKeyboardFocusOn(struct weston_layout_surface *ivisurf)
+{
+ /* not supported */
+ (void)ivisurf;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_GetKeyboardFocusSurfaceId(struct weston_layout_surface **pSurfaceId)
+{
+ /* not supported */
+ (void)pSurfaceId;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetDestinationRectangle(struct weston_layout_surface *ivisurf,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetDestinationRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destX = x;
+ prop->destY = y;
+ prop->destWidth = width;
+ prop->destHeight = height;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_DEST_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetDimension(struct weston_layout_surface *ivisurf, uint32_t *pDimension)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("weston_layout_surfaceSetDimension: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destWidth = pDimension[0];
+ prop->destHeight = pDimension[1];
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_DIMENSION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetDimension(struct weston_layout_surface *ivisurf,
+ uint32_t *pDimension)
+{
+ if (ivisurf == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("weston_layout_surfaceGetDimension: invalid argument\n");
+ return -1;
+ }
+
+ pDimension[0] = ivisurf->prop.destWidth;
+ pDimension[1] = ivisurf->prop.destHeight;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetPosition(struct weston_layout_surface *ivisurf,
+ int32_t *pPosition)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL || pPosition == NULL) {
+ weston_log("weston_layout_surfaceSetPosition: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destX = pPosition[0];
+ prop->destY = pPosition[1];
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_POSITION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetPosition(struct weston_layout_surface *ivisurf,
+ int32_t *pPosition)
+{
+ if (ivisurf == NULL || pPosition == NULL) {
+ weston_log("weston_layout_surfaceGetPosition: invalid argument\n");
+ return -1;
+ }
+
+ pPosition[0] = ivisurf->prop.destX;
+ pPosition[1] = ivisurf->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetOrientation(struct weston_layout_surface *ivisurf,
+ uint32_t orientation)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->orientation = orientation;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_ORIENTATION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetOrientation(struct weston_layout_surface *ivisurf,
+ uint32_t *pOrientation)
+{
+ if (ivisurf == NULL || pOrientation == NULL) {
+ weston_log("weston_layout_surfaceGetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ *pOrientation = ivisurf->prop.orientation;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetPixelformat(struct weston_layout_layer *ivisurf, uint32_t *pPixelformat)
+{
+ /* not supported */
+ (void)ivisurf;
+ (void)pPixelformat;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetChromaKey(struct weston_layout_surface *ivisurf, uint32_t* pColor)
+{
+ /* not supported */
+ (void)ivisurf;
+ (void)pColor;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_screenAddLayer(struct weston_layout_screen *iviscrn,
+ struct weston_layout_layer *addlayer)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_layer *next = NULL;
+ int is_layer_in_scrn = 0;
+
+ if (iviscrn == NULL || addlayer == NULL) {
+ weston_log("weston_layout_screenAddLayer: invalid argument\n");
+ return -1;
+ }
+
+ is_layer_in_scrn = is_layer_in_screen(addlayer, iviscrn);
+ if (is_layer_in_scrn == 1) {
+ weston_log("weston_layout_screenAddLayer: addlayer is already available\n");
+ return 0;
+ }
+
+ wl_list_for_each_safe(ivilayer, next, &layout->list_layer, link) {
+ if (ivilayer->id_layer == addlayer->id_layer) {
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ wl_list_init(&ivilayer->pending.link);
+ wl_list_insert(&iviscrn->pending.list_layer,
+ &ivilayer->pending.link);
+ break;
+ }
+ }
+
+ iviscrn->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_screenSetRenderOrder(struct weston_layout_screen *iviscrn,
+ struct weston_layout_layer **pLayer,
+ const uint32_t number)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+ uint32_t *id_layer = NULL;
+ uint32_t i = 0;
+
+ if (iviscrn == NULL) {
+ weston_log("weston_layout_screenSetRenderOrder: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_init(&iviscrn->pending.list_layer);
+
+ if (pLayer == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < number; i++) {
+ id_layer = &pLayer[i]->id_layer;
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ if (*id_layer == ivilayer->id_layer) {
+ continue;
+ }
+
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ wl_list_init(&ivilayer->pending.link);
+ wl_list_insert(&iviscrn->pending.list_layer,
+ &ivilayer->pending.link);
+ break;
+ }
+ }
+
+ iviscrn->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_takeScreenshot(struct weston_layout_screen *iviscrn,
+ const char *filename)
+{
+ struct weston_output *output = NULL;
+ cairo_surface_t *cairo_surf = NULL;
+ int32_t i = 0;
+ int32_t width = 0;
+ int32_t height = 0;
+ int32_t stride = 0;
+ uint8_t *readpixs = NULL;
+ uint8_t *writepixs = NULL;
+ uint8_t *d = NULL;
+ uint8_t *s = NULL;
+
+ if (iviscrn == NULL || filename == NULL) {
+ weston_log("weston_layout_takeScreenshot: invalid argument\n");
+ return -1;
+ }
+
+ output = iviscrn->output;
+ output->disable_planes--;
+
+ width = output->current_mode->width;
+ height = output->current_mode->height;
+ stride = width * (PIXMAN_FORMAT_BPP(output->compositor->read_format) / 8);
+
+ readpixs = malloc(stride * height);
+ if (readpixs == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+ writepixs = malloc(stride * height);
+ if (writepixs == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ output->compositor->renderer->read_pixels(output,
+ output->compositor->read_format, readpixs,
+ 0, 0, width, height);
+
+ s = readpixs;
+ d = writepixs + stride * (height - 1);
+
+ for (i = 0; i < height; i++) {
+ memcpy(d, s, stride);
+ d -= stride;
+ s += stride;
+ }
+
+ cairo_surf = cairo_image_surface_create_for_data(writepixs,
+ CAIRO_FORMAT_ARGB32,
+ width, height, stride);
+ cairo_surface_write_to_png(cairo_surf, filename);
+ cairo_surface_destroy(cairo_surf);
+ free(writepixs);
+ free(readpixs);
+ writepixs = NULL;
+ readpixs = NULL;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_takeLayerScreenshot(const char *filename, struct weston_layout_layer *ivilayer)
+{
+ /* not supported */
+ (void)filename;
+ (void)ivilayer;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_takeSurfaceScreenshot(const char *filename,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_compositor *ec = layout->compositor;
+ cairo_surface_t *cairo_surf;
+ int32_t width;
+ int32_t height;
+ int32_t stride;
+ uint8_t *pixels;
+
+ if (filename == NULL || ivisurf == NULL) {
+ weston_log("weston_layout_takeSurfaceScreenshot: invalid argument\n");
+ return -1;
+ }
+
+ width = ivisurf->prop.destWidth;
+ height = ivisurf->prop.destHeight;
+ stride = width * (PIXMAN_FORMAT_BPP(ec->read_format) / 8);
+
+ pixels = malloc(stride * height);
+ if (pixels == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ ec->renderer->read_surface_pixels(ivisurf->surface,
+ ec->read_format, pixels,
+ 0, 0, width, height);
+
+ cairo_surf = cairo_image_surface_create_for_data(pixels,
+ CAIRO_FORMAT_ARGB32,
+ width, height, stride);
+ cairo_surface_write_to_png(cairo_surf, filename);
+ cairo_surface_destroy(cairo_surf);
+
+ free(pixels);
+ pixels = NULL;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_SetOptimizationMode(uint32_t id, uint32_t mode)
+{
+ /* not supported */
+ (void)id;
+ (void)mode;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_GetOptimizationMode(uint32_t id, uint32_t *pMode)
+{
+ /* not supported */
+ (void)id;
+ (void)pMode;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerAddNotification(struct weston_layout_layer *ivilayer,
+ layerPropertyNotificationFunc callback,
+ void *userdata)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+
+ if (ivilayer == NULL || callback == NULL) {
+ weston_log("weston_layout_layerAddNotification: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&ivilayer->list_notification, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerRemoveNotification(struct weston_layout_layer *ivilayer)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+ struct link_layerPropertyNotification *next = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerRemoveNotification: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(notification, next,
+ &ivilayer->list_notification, link) {
+ if (!wl_list_empty(&notification->link)) {
+ wl_list_remove(&notification->link);
+ }
+ free(notification);
+ notification = NULL;
+ }
+ wl_list_init(&ivilayer->list_notification);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getPropertiesOfSurface(struct weston_layout_surface *ivisurf,
+ struct weston_layout_SurfaceProperties *pSurfaceProperties)
+{
+ if (ivisurf == NULL || pSurfaceProperties == NULL) {
+ weston_log("weston_layout_getPropertiesOfSurface: invalid argument\n");
+ return -1;
+ }
+
+ *pSurfaceProperties = ivisurf->prop;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerAddSurface(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *addsurf)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_surface *next = NULL;
+ int is_surf_in_layer = 0;
+
+ if (ivilayer == NULL || addsurf == NULL) {
+ weston_log("weston_layout_layerAddSurface: invalid argument\n");
+ return -1;
+ }
+
+ is_surf_in_layer = is_surface_in_layer(addsurf, ivilayer);
+ if (is_surf_in_layer == 1) {
+ weston_log("weston_layout_layerAddSurface: addsurf is already available\n");
+ return 0;
+ }
+
+ wl_list_for_each_safe(ivisurf, next, &layout->list_surface, link) {
+ if (ivisurf->id_surface == addsurf->id_surface) {
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ wl_list_insert(&ivilayer->pending.list_surface,
+ &ivisurf->pending.link);
+ break;
+ }
+ }
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerRemoveSurface(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *remsurf)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_surface *next = NULL;
+
+ if (ivilayer == NULL || remsurf == NULL) {
+ weston_log("weston_layout_layerRemoveSurface: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(ivisurf, next,
+ &ivilayer->pending.list_surface, pending.link) {
+ if (ivisurf->id_surface == remsurf->id_surface) {
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetSourceRectangle(struct weston_layout_surface *ivisurf,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetSourceRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->sourceX = x;
+ prop->sourceY = y;
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_commitChanges(void)
+{
+ struct weston_layout *layout = get_instance();
+
+ commit_list_surface(layout);
+ commit_list_layer(layout);
+ commit_list_screen(layout);
+
+ commit_changes(layout);
+ send_prop(layout);
+ weston_compositor_schedule_repaint(layout->compositor);
+
+ return 0;
+}
diff --git a/ivi-shell/weston-layout.h b/ivi-shell/weston-layout.h
new file mode 100644
index 0000000..871fea1
--- /dev/null
+++ b/ivi-shell/weston-layout.h
@@ -0,0 +1,920 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * The weston-layout library supports API set of controlling properties of
+ * surface and layer which groups surfaces. An unique ID whose type is integer
+ * is required to create surface and layer. With the unique ID, surface and
+ * layer are identified to control them. The API set consists of APIs to control
+ * properties of surface and layers about followings,
+ * - visibility.
+ * - opacity.
+ * - clipping (x,y,width,height).
+ * - position and size of it to be displayed.
+ * - orientation per 90 degree.
+ * - add or remove surfaces to a layer.
+ * - order of surfaces/layers in layer/screen to be displayed.
+ * - commit to apply property changes.
+ * - notifications of property change.
+ *
+ * Management of surfaces and layers grouping these surfaces are common way in
+ * In-Vehicle Infotainment system, which integrate several domains in one system.
+ * A layer is allocated to a domain in order to control application surfaces
+ * grouped to the layer all together.
+ */
+
+#ifndef _WESTON_LAYOUT_H_
+#define _WESTON_LAYOUT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "compositor.h"
+
+struct weston_layout_SurfaceProperties
+{
+ float opacity;
+ uint32_t sourceX;
+ uint32_t sourceY;
+ uint32_t sourceWidth;
+ uint32_t sourceHeight;
+ uint32_t origSourceWidth;
+ uint32_t origSourceHeight;
+ int32_t destX;
+ int32_t destY;
+ uint32_t destWidth;
+ uint32_t destHeight;
+ uint32_t orientation;
+ uint32_t visibility;
+ uint32_t frameCounter;
+ uint32_t drawCounter;
+ uint32_t updateCounter;
+ uint32_t pixelformat;
+ uint32_t nativeSurface;
+ uint32_t inputDevicesAcceptance;
+ uint32_t chromaKeyEnabled;
+ uint32_t chromaKeyRed;
+ uint32_t chromaKeyGreen;
+ uint32_t chromaKeyBlue;
+ int32_t creatorPid;
+};
+
+struct weston_layout_LayerProperties
+{
+ float opacity;
+ uint32_t sourceX;
+ uint32_t sourceY;
+ uint32_t sourceWidth;
+ uint32_t sourceHeight;
+ uint32_t origSourceWidth;
+ uint32_t origSourceHeight;
+ int32_t destX;
+ int32_t destY;
+ uint32_t destWidth;
+ uint32_t destHeight;
+ uint32_t orientation;
+ uint32_t visibility;
+ uint32_t type;
+ uint32_t chromaKeyEnabled;
+ uint32_t chromaKeyRed;
+ uint32_t chromaKeyGreen;
+ uint32_t chromaKeyBlue;
+ int32_t creatorPid;
+};
+
+struct weston_layout_layer;
+struct weston_layout_surface;
+struct weston_layout_screen;
+
+typedef struct weston_layout_surface* weston_layout_surface_ptr;
+typedef struct weston_layout_layer* weston_layout_layer_ptr;
+typedef struct weston_layout_screen* weston_layout_screen_ptr;
+
+#define IVI_BIT(x) (1 << (x))
+enum weston_layout_notification_mask {
+ IVI_NOTIFICATION_OPACITY = IVI_BIT(1),
+ IVI_NOTIFICATION_SOURCE_RECT = IVI_BIT(2),
+ IVI_NOTIFICATION_DEST_RECT = IVI_BIT(3),
+ IVI_NOTIFICATION_DIMENSION = IVI_BIT(4),
+ IVI_NOTIFICATION_POSITION = IVI_BIT(5),
+ IVI_NOTIFICATION_ORIENTATION = IVI_BIT(6),
+ IVI_NOTIFICATION_VISIBILITY = IVI_BIT(7),
+ IVI_NOTIFICATION_PIXELFORMAT = IVI_BIT(8),
+ IVI_NOTIFICATION_ADD = IVI_BIT(9),
+ IVI_NOTIFICATION_ALL = 0xFFFF
+};
+
+typedef void(*layerPropertyNotificationFunc)(struct weston_layout_layer *ivilayer,
+ struct weston_layout_LayerProperties*,
+ enum weston_layout_notification_mask mask,
+ void *userdata);
+
+typedef void(*surfacePropertyNotificationFunc)(struct weston_layout_surface *ivisurf,
+ struct weston_layout_SurfaceProperties*,
+ enum weston_layout_notification_mask mask,
+ void *userdata);
+
+typedef void(*layerCreateNotificationFunc)(struct weston_layout_layer *ivilayer,
+ void *userdata);
+
+typedef void(*layerRemoveNotificationFunc)(struct weston_layout_layer *ivilayer,
+ void *userdata);
+
+typedef void(*surfaceCreateNotificationFunc)(struct weston_layout_surface *ivisurf,
+ void *userdata);
+
+typedef void(*surfaceRemoveNotificationFunc)(struct weston_layout_surface *ivisurf,
+ void *userdata);
+
+typedef void(*surfaceConfigureNotificationFunc)(struct weston_layout_surface *ivisurf,
+ void *userdata);
+
+/**
+ * \brief to be called by ivi-shell in order to set initail view of
+ * weston_surface.
+ */
+struct weston_view *
+weston_layout_get_weston_view(struct weston_layout_surface *surface);
+
+/**
+ * \brief initialize weston-layout
+ */
+void
+weston_layout_initWithCompositor(struct weston_compositor *ec);
+
+/**
+ * \brief register for notification when layer is created
+ */
+int32_t
+weston_layout_setNotificationCreateLayer(layerCreateNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when layer is removed
+ */
+int32_t
+weston_layout_setNotificationRemoveLayer(layerRemoveNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is created
+ */
+int32_t
+weston_layout_setNotificationCreateSurface(surfaceCreateNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is removed
+ */
+int32_t
+weston_layout_setNotificationRemoveSurface(surfaceRemoveNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is configured
+ */
+int32_t
+weston_layout_setNotificationConfigureSurface(surfaceConfigureNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief get id of surface from weston_layout_surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+uint32_t
+weston_layout_getIdOfSurface(struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief get id of layer from weston_layout_layer
+ *
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+uint32_t
+weston_layout_getIdOfLayer(struct weston_layout_layer *ivilayer);
+
+/**
+ * \brief get weston_layout_layer from id of layer
+ *
+ * \return (struct weston_layout_layer *)
+ * if the method call was successful
+ * \return NULL if the client can not call the method on the service.
+ */
+struct weston_layout_layer *
+weston_layout_getLayerFromId(uint32_t id_layer);
+
+/**
+ * \brief get weston_layout_surface from id of surface
+ *
+ * \return (struct weston_layout_surface *)
+ * if the method call was successful
+ * \return NULL if the client can not call the method on the service.
+ */
+struct weston_layout_surface *
+weston_layout_getSurfaceFromId(uint32_t id_surface);
+
+/**
+ * \brief get weston_layout_screen from id of screen
+ *
+ * \return (struct weston_layout_screen *)
+ * if the method call was successful
+ * \return NULL if the client can not call the method on the service.
+ */
+struct weston_layout_screen *
+weston_layout_getScreenFromId(uint32_t id_screen);
+
+/**
+ * \brief Get the screen resolution of a specific screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getScreenResolution(struct weston_layout_screen *iviscrn,
+ uint32_t *pWidth,
+ uint32_t *pHeight);
+
+/**
+ * \brief register for notification on property changes of surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceAddNotification(struct weston_layout_surface *ivisurf,
+ surfacePropertyNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief remove notification on property changes of surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceRemoveNotification(struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief Create a surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+struct weston_layout_surface *
+weston_layout_surfaceCreate(struct weston_surface *wl_surface,
+ uint32_t id_surface);
+
+/**
+ * \brief initialize weston_layout_surface dest/source width and height
+ */
+void
+weston_layout_surfaceConfigure(struct weston_layout_surface *ivisurf,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Remove a surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceRemove(struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief Set from which kind of devices the surface can accept input events.
+ * By default, a surface accept input events from all kind of devices (keyboards, pointer, ...)
+ * By calling this function, you can adjust surface preferences. Note that this function only
+ * adjust the acceptance for the specified devices. Non specified are keept untouched.
+ *
+ * Typicall use case for this function is when dealing with pointer or touch events.
+ * Those are normally dispatched to the first visible surface below the coordinate.
+ * If you want a different behavior (i.e. forward events to an other surface below the coordinate,
+ * you can set all above surfaces to refuse input events)
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_UpdateInputEventAcceptanceOn(struct weston_layout_surface *ivisurf,
+ uint32_t devices,
+ uint32_t acceptance);
+
+/**
+ * \brief Get the layer properties
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getPropertiesOfLayer(struct weston_layout_layer *ivilayer,
+ struct weston_layout_LayerProperties *pLayerProperties);
+
+/**
+ * \brief Get the number of hardware layers of a screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getNumberOfHardwareLayers(uint32_t id_screen,
+ uint32_t *pNumberOfHardwareLayers);
+
+/**
+ * \brief Get the screens
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getScreens(uint32_t *pLength, weston_layout_screen_ptr **ppArray);
+
+/**
+ * \brief Get the screens under the given layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getScreensUnderLayer(struct weston_layout_layer *ivilayer,
+ uint32_t *pLength,
+ weston_layout_screen_ptr **ppArray);
+
+/**
+ * \brief Get all Layers which are currently registered and managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getLayers(uint32_t *pLength, weston_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Layers of the given screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getLayersOnScreen(struct weston_layout_screen *iviscrn,
+ uint32_t *pLength,
+ weston_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Layers under the given surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getLayersUnderSurface(struct weston_layout_surface *ivisurf,
+ uint32_t *pLength,
+ weston_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Surfaces which are currently registered and managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getSurfaces(uint32_t *pLength, weston_layout_surface_ptr **ppArray);
+
+/**
+ * \brief Get all Surfaces which are currently registered to a given layer and are managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getSurfacesOnLayer(struct weston_layout_layer *ivilayer,
+ uint32_t *pLength,
+ weston_layout_surface_ptr **ppArray);
+
+/**
+ * \brief Create a layer which should be managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+struct weston_layout_layer *
+weston_layout_layerCreateWithDimension(uint32_t id_layer,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Removes a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerRemove(struct weston_layout_layer *ivilayer);
+
+/**
+ * \brief Get the current type of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetType(struct weston_layout_layer *ivilayer,
+ uint32_t *pLayerType);
+
+/**
+ * \brief Set the visibility of a layer. If a layer is not visible, the layer and its
+ * surfaces will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetVisibility(struct weston_layout_layer *ivilayer,
+ uint32_t newVisibility);
+
+/**
+ * \brief Get the visibility of a layer. If a layer is not visible, the layer and its
+ * surfaces will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetVisibility(struct weston_layout_layer *ivilayer,
+ uint32_t *pVisibility);
+
+/**
+ * \brief Set the opacity of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetOpacity(struct weston_layout_layer *ivilayer, float opacity);
+
+/**
+ * \brief Get the opacity of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetOpacity(struct weston_layout_layer *ivilayer, float *pOpacity);
+
+/**
+ * \brief Set the area of a layer which should be used for the rendering.
+ * Only this part will be visible.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetSourceRectangle(struct weston_layout_layer *ivilayer,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Set the destination area on the display for a layer.
+ * The layer will be scaled and positioned to this rectangle for rendering
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetDestinationRectangle(struct weston_layout_layer *ivilayer,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Get the horizontal and vertical dimension of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetDimension(struct weston_layout_layer *ivilayer,
+ uint32_t *pDimension);
+
+/**
+ * \brief Set the horizontal and vertical dimension of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetDimension(struct weston_layout_layer *ivilayer,
+ uint32_t *pDimension);
+
+/**
+ * \brief Get the horizontal and vertical position of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetPosition(struct weston_layout_layer *ivilayer,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the horizontal and vertical position of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetPosition(struct weston_layout_layer *ivilayer,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the orientation of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetOrientation(struct weston_layout_layer *ivilayer,
+ uint32_t orientation);
+
+/**
+ * \brief Gets the orientation of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetOrientation(struct weston_layout_layer *ivilayer,
+ uint32_t *pOrientation);
+
+/**
+ * \brief Sets the color value which defines the transparency value.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetChromaKey(struct weston_layout_layer *ivilayer,
+ uint32_t* pColor);
+
+/**
+ * \brief Sets render order of surfaces within one layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetRenderOrder(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface **pSurface,
+ uint32_t number);
+
+/**
+ * \brief Get the capabilities of a layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetCapabilities(struct weston_layout_layer *ivilayer,
+ uint32_t *pCapabilities);
+
+/**
+ * \brief Get the possible capabilities of a layertype
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerTypeGetCapabilities(uint32_t layerType,
+ uint32_t *pCapabilities);
+
+/**
+ * \brief Create the logical surface, which has no native buffer associated
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceInitialize(struct weston_layout_surface **pSurface);
+
+/**
+ * \brief Set the visibility of a surface.
+ * If a surface is not visible it will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetVisibility(struct weston_layout_surface *ivisurf,
+ uint32_t newVisibility);
+
+/**
+ * \brief Get the visibility of a surface.
+ * If a surface is not visible it will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetVisibility(struct weston_layout_surface *ivisurf,
+ uint32_t *pVisibility);
+
+/**
+ * \brief Set the opacity of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetOpacity(struct weston_layout_surface *ivisurf,
+ float opacity);
+
+/**
+ * \brief Get the opacity of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetOpacity(struct weston_layout_surface *ivisurf,
+ float *pOpacity);
+
+/**
+ * \brief Set the keyboard focus on a certain surface
+ * To receive keyboard events, 2 conditions must be fulfilled:
+ * 1- The surface must accept events from keyboard. See ilm_UpdateInputEventAcceptanceOn
+ * 2- The keyboard focus must be set on that surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_SetKeyboardFocusOn(struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief Get the indentifier of the surface which hold the keyboard focus
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_GetKeyboardFocusSurfaceId(struct weston_layout_surface **pSurfaceId);
+
+/**
+ * \brief Set the destination area of a surface within a layer for rendering.
+ * The surface will be scaled to this rectangle for rendering.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetDestinationRectangle(struct weston_layout_surface *ivisurf,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Set the horizontal and vertical dimension of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetDimension(struct weston_layout_surface *ivisurf,
+ uint32_t *pDimension);
+
+/**
+ * \brief Get the horizontal and vertical dimension of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetDimension(struct weston_layout_surface *ivisurf,
+ uint32_t *pDimension);
+
+/**
+ * \brief Sets the horizontal and vertical position of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetPosition(struct weston_layout_surface *ivisurf,
+ int32_t *pPosition);
+
+/**
+ * \brief Get the horizontal and vertical position of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetPosition(struct weston_layout_surface *ivisurf,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the orientation of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetOrientation(struct weston_layout_surface *ivisurf,
+ uint32_t orientation);
+
+/**
+ * \brief Gets the orientation of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetOrientation(struct weston_layout_surface *ivisurf,
+ uint32_t *pOrientation);
+
+/**
+ * \brief Gets the pixelformat of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetPixelformat(struct weston_layout_layer *ivisurf,
+ uint32_t *pPixelformat);
+
+/**
+ * \brief Sets the color value which defines the transparency value of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetChromaKey(struct weston_layout_surface *ivisurf,
+ uint32_t* pColor);
+
+/**
+ * \brief Add a layer to a screen which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_screenAddLayer(struct weston_layout_screen *iviscrn,
+ struct weston_layout_layer *addlayer);
+
+/**
+ * \brief Sets render order of layers on a display
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_screenSetRenderOrder(struct weston_layout_screen *iviscrn,
+ struct weston_layout_layer **pLayer,
+ const uint32_t number);
+
+/**
+ * \brief Take a screenshot from the current displayed layer scene.
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_takeScreenshot(struct weston_layout_screen *iviscrn,
+ const char *filename);
+
+/**
+ * \brief Take a screenshot of a certain layer
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_takeLayerScreenshot(const char *filename,
+ struct weston_layout_layer *ivilayer);
+
+/**
+ * \brief Take a screenshot of a certain surface
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_takeSurfaceScreenshot(const char *filename,
+ struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief Enable or disable a rendering optimization
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_SetOptimizationMode(uint32_t id, uint32_t mode);
+
+/**
+ * \brief Get the current enablement for an optimization
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_GetOptimizationMode(uint32_t id, uint32_t *pMode);
+
+/**
+ * \brief register for notification on property changes of layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerAddNotification(struct weston_layout_layer *ivilayer,
+ layerPropertyNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief remove notification on property changes of layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerRemoveNotification(struct weston_layout_layer *ivilayer);
+
+/**
+ * \brief Get the surface properties
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getPropertiesOfSurface(struct weston_layout_surface *ivisurf,
+ struct weston_layout_SurfaceProperties *pSurfaceProperties);
+
+/**
+ * \brief Add a surface to a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerAddSurface(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *addsurf);
+
+/**
+ * \brief Removes a surface from a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerRemoveSurface(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *remsurf);
+
+/**
+ * \brief Set the area of a surface which should be used for the rendering.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetSourceRectangle(struct weston_layout_surface *ivisurf,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Commit all changes and execute all enqueued commands since last commit.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_commitChanges(void);
+
+#ifdef __cplusplus
+} /**/
+#endif /* __cplusplus */
+
+#endif /* _WESTON_LAYOUT_H_ */
--
1.8.3.1
Nobuhiko Tanibata
2014-03-15 05:56:34 UTC
Permalink
API set of controlling properties of surface and layer which groups
surfaces. An unique ID whose type is integer is required to create
surface and layer. With the unique ID, surface and layer are identified
to control them. The API set consists of APIs to control properties of
surface and layers about followings,

- visibility.
- opacity.
- clipping (x,y,width,height).
- position and size of it to be displayed.
- orientation per 90 degree.
- add or remove surfaces to a layer.
- order of surfaces/layers in layer/screen to be displayed.
- commit to apply property changes.
- notifications of property change.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- move this patch in front of ivi-shell patch to be compiled successfully.
- unsupport weston_layout_takeSurfaceScreenshot because implementation needs to
be discussed more. It is pending.
- support inherit propoerties of id_surface when client attaches another
wl_surface with id_surface after destroying ivi_surface once.

Makefile.am | 1 +
configure.ac | 15 +-
ivi-shell/Makefile.am | 30 +
ivi-shell/weston-layout.c | 2631 +++++++++++++++++++++++++++++++++++++++++++++
ivi-shell/weston-layout.h | 934 ++++++++++++++++
5 files changed, 3610 insertions(+), 1 deletion(-)
create mode 100644 ivi-shell/Makefile.am
create mode 100644 ivi-shell/weston-layout.c
create mode 100644 ivi-shell/weston-layout.h

diff --git a/Makefile.am b/Makefile.am
index f22c542..1bc35e2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,6 +11,7 @@ SUBDIRS = \
src \
$(xwayland_subdir) \
desktop-shell \
+ ivi-shell \
clients \
data \
protocol \
diff --git a/configure.ac b/configure.ac
index cce1850..4c0a90f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -409,6 +409,16 @@ if test "x$enable_dbus" != "xno"; then
fi
AM_CONDITIONAL(ENABLE_DBUS, test "x$enable_dbus" = "xyes")

+# ivi-shell support
+AC_ARG_ENABLE(ivi-shell,
+ AS_HELP_STRING([--disable-ivi-shell],
+ [do not build ivi-shell server plugin and client]),,
+ enable_ivi_shell=yes)
+AM_CONDITIONAL(ENABLE_IVI_SHELL, test "x$enable_ivi_shell" = "xyes")
+if test x$enable_ivi_shell = xyes; then
+ PKG_CHECK_MODULES(IVI_SHELL, [cairo])
+fi
+
AC_ARG_ENABLE(wcap-tools, [ --disable-wcap-tools],, enable_wcap_tools=yes)
AM_CONDITIONAL(BUILD_WCAP_TOOLS, test x$enable_wcap_tools = xyes)
if test x$enable_wcap_tools = xyes; then
@@ -505,7 +515,8 @@ AC_CONFIG_FILES([Makefile
data/Makefile
protocol/Makefile
man/Makefile
- tests/Makefile])
+ tests/Makefile
+ ivi-shell/Makefile])
AC_OUTPUT

AC_MSG_RESULT([
@@ -519,6 +530,8 @@ AC_MSG_RESULT([
XWayland ${enable_xwayland}
dbus ${enable_dbus}

+ ivi-shell ${enable_ivi_shell}
+
Build wcap utility ${enable_wcap_tools}

weston-launch utility ${enable_weston_launch}
diff --git a/ivi-shell/Makefile.am b/ivi-shell/Makefile.am
new file mode 100644
index 0000000..4d54c2d
--- /dev/null
+++ b/ivi-shell/Makefile.am
@@ -0,0 +1,30 @@
+moduledir = $(libdir)/weston
+
+module_LTLIBRARIES = \
+ $(libweston_layout)
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/shared \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src \
+ -DDATADIR='"$(datadir)"' \
+ -DMODULEDIR='"$(moduledir)"' \
+ -DLIBEXECDIR='"$(libexecdir)"' \
+ -DIN_WESTON
+
+westonincludedir = $(includedir)/weston
+westoninclude_HEADERS =
+
+if ENABLE_IVI_SHELL
+westoninclude_HEADERS += \
+ weston-layout.h
+
+libweston_layout = libweston-layout.la
+libweston_layout_la_LDFLAGS = -avoid-version
+libweston_layout_la_LIBADD = $(IVI_SHELL_LIBS) ../shared/libshared.la
+libweston_layout_la_CFLAGS = $(GCC_CFLAGS) $(IVI_SHELL_CFLAGS)
+libweston_layout_la_SOURCES = \
+ weston-layout.c \
+ weston-layout.h
+
+endif
diff --git a/ivi-shell/weston-layout.c b/ivi-shell/weston-layout.c
new file mode 100644
index 0000000..9cb571a
--- /dev/null
+++ b/ivi-shell/weston-layout.c
@@ -0,0 +1,2631 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * Implementation of weston-layout library. The actual view on screen is
+ * not updated till calling weston_layout_commitChanges. A overview from
+ * calling API for updating properties of surfaces/layer to asking compositor
+ * to compose them by using weston_compositor_schedule_repaint,
+ * 0/ initialize this library by weston_layout_initWithCompositor
+ * with (struct weston_compositor *ec) from ivi-shell.
+ * 1/ When a API for updating properties of surface/layer, it updates
+ * pending prop of weston_layout_surface/layer/screen which are structure to
+ * store properties.
+ * 2/ Before calling commitChanges, in case of calling a API to get a property,
+ * return current property, not pending property.
+ * 3/ At the timing of calling weston_layout_commitChanges, pending properties
+ * are applied
+ * to properties.
+ * 4/ According properties, set transformation by using weston_matrix and
+ * weston_view per surfaces and layers in while loop.
+ * 5/ Set damage and trigger transform by using weston_view_geometry_dirty and
+ * weston_view_geometry_dirty.
+ * 6/ Notify update of properties.
+ * 7/ Trigger composition by weston_compositor_schedule_repaint.
+ *
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+#include <cairo.h>
+
+#include "compositor.h"
+#include "weston-layout.h"
+
+enum weston_layout_surface_orientation {
+ WESTON_LAYOUT_SURFACE_ORIENTATION_0_DEGREES = 0,
+ WESTON_LAYOUT_SURFACE_ORIENTATION_90_DEGREES = 1,
+ WESTON_LAYOUT_SURFACE_ORIENTATION_180_DEGREES = 2,
+ WESTON_LAYOUT_SURFACE_ORIENTATION_270_DEGREES = 3,
+};
+
+enum weston_layout_surface_pixelformat {
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_R_8 = 0,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGB_888 = 1,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_8888 = 2,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGB_565 = 3,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_5551 = 4,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_6661 = 5,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_4444 = 6,
+ WESTON_LAYOUT_SURFACE_PIXELFORMAT_UNKNOWN = 7,
+};
+
+struct link_layer {
+ struct weston_layout_layer *ivilayer;
+ struct wl_list link;
+};
+
+struct link_screen {
+ struct weston_layout_screen *iviscrn;
+ struct wl_list link;
+};
+
+struct link_layerPropertyNotification {
+ layerPropertyNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfacePropertyNotification {
+ surfacePropertyNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_layerCreateNotification {
+ layerCreateNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_layerRemoveNotification {
+ layerRemoveNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceCreateNotification {
+ surfaceCreateNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceRemoveNotification {
+ surfaceRemoveNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceConfigureNotification {
+ surfaceConfigureNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct weston_layout;
+
+struct weston_layout_surface {
+ struct wl_list link;
+ struct wl_list list_notification;
+ struct wl_list list_layer;
+ uint32_t update_count;
+ uint32_t id_surface;
+
+ struct weston_layout *layout;
+ struct weston_surface *surface;
+ struct weston_view *view;
+
+ uint32_t buffer_width;
+ uint32_t buffer_height;
+
+ struct wl_listener surface_destroy_listener;
+ struct weston_transform surface_rotation;
+ struct weston_transform layer_rotation;
+ struct weston_transform surface_pos;
+ struct weston_transform layer_pos;
+ struct weston_transform scaling;
+ struct weston_layout_SurfaceProperties prop;
+ int32_t pixelformat;
+ uint32_t event_mask;
+
+ struct {
+ struct weston_layout_SurfaceProperties prop;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list link;
+ struct wl_list list_layer;
+ } order;
+};
+
+struct weston_layout_layer {
+ struct wl_list link;
+ struct wl_list list_notification;
+ struct wl_list list_screen;
+ uint32_t id_layer;
+
+ struct weston_layout *layout;
+ struct weston_layer el;
+
+ struct weston_layout_LayerProperties prop;
+ uint32_t event_mask;
+
+ struct {
+ struct weston_layout_LayerProperties prop;
+ struct wl_list list_surface;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list list_surface;
+ struct wl_list link;
+ } order;
+};
+
+struct weston_layout_screen {
+ struct wl_list link;
+ uint32_t id_screen;
+
+ struct weston_layout *layout;
+ struct weston_output *output;
+
+ uint32_t event_mask;
+
+ struct {
+ struct wl_list list_layer;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list list_layer;
+ struct wl_list link;
+ } order;
+};
+
+struct weston_layout {
+ struct weston_compositor *compositor;
+
+ struct wl_list list_surface;
+ struct wl_list list_layer;
+ struct wl_list list_screen;
+
+ struct {
+ struct wl_list list_create;
+ struct wl_list list_remove;
+ } layer_notification;
+
+ struct {
+ struct wl_list list_create;
+ struct wl_list list_remove;
+ struct wl_list list_configure;
+ } surface_notification;
+
+ /* to enable displaying cursor*/
+ int32_t is_cursor_enabled;
+};
+
+struct weston_layout ivilayout = {0};
+
+static struct weston_layout *
+get_instance(void)
+{
+ return &ivilayout;
+}
+
+/**
+ * Internal API to add/remove a surface from layer.
+ */
+static void
+add_ordersurface_to_layer(struct weston_layout_surface *ivisurf,
+ struct weston_layout_layer *ivilayer)
+{
+ struct link_layer *link_layer = NULL;
+
+ link_layer = malloc(sizeof *link_layer);
+ if (link_layer == NULL) {
+ weston_log("fails to allocate memory\n");
+ return;
+ }
+
+ link_layer->ivilayer = ivilayer;
+ wl_list_init(&link_layer->link);
+ wl_list_insert(&ivisurf->list_layer, &link_layer->link);
+}
+
+static void
+remove_ordersurface_from_layer(struct weston_layout_surface *ivisurf)
+{
+ struct link_layer *link_layer = NULL;
+ struct link_layer *next = NULL;
+
+ wl_list_for_each_safe(link_layer, next, &ivisurf->list_layer, link) {
+ if (!wl_list_empty(&link_layer->link)) {
+ wl_list_remove(&link_layer->link);
+ }
+ free(link_layer);
+ }
+ wl_list_init(&ivisurf->list_layer);
+}
+
+/**
+ * Internal API to add/remove a layer from screen.
+ */
+static void
+add_orderlayer_to_screen(struct weston_layout_layer *ivilayer,
+ struct weston_layout_screen *iviscrn)
+{
+ struct link_screen *link_scrn = NULL;
+
+ link_scrn = malloc(sizeof *link_scrn);
+ if (link_scrn == NULL) {
+ weston_log("fails to allocate memory\n");
+ return;
+ }
+
+ link_scrn->iviscrn = iviscrn;
+ wl_list_init(&link_scrn->link);
+ wl_list_insert(&ivilayer->list_screen, &link_scrn->link);
+}
+
+static void
+remove_orderlayer_from_screen(struct weston_layout_layer *ivilayer)
+{
+ struct link_screen *link_scrn = NULL;
+ struct link_screen *next = NULL;
+
+ wl_list_for_each_safe(link_scrn, next, &ivilayer->list_screen, link) {
+ if (!wl_list_empty(&link_scrn->link)) {
+ wl_list_remove(&link_scrn->link);
+ }
+ free(link_scrn);
+ }
+ wl_list_init(&ivilayer->list_screen);
+}
+
+/**
+ * Internal API to add/remove a layer from screen.
+ */
+static struct weston_layout_surface *
+get_surface(struct wl_list *list_surf, uint32_t id_surface)
+{
+ struct weston_layout_surface *ivisurf;
+
+ wl_list_for_each(ivisurf, list_surf, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+static struct weston_layout_layer *
+get_layer(struct wl_list *list_layer, uint32_t id_layer)
+{
+ struct weston_layout_layer *ivilayer;
+
+ wl_list_for_each(ivilayer, list_layer, link) {
+ if (ivilayer->id_layer == id_layer) {
+ return ivilayer;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Called at destruction of ivi_surface
+ */
+static void
+westonsurface_destroy_from_ivisurface(struct wl_listener *listener, void *data)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+
+ ivisurf = container_of(listener, struct weston_layout_surface,
+ surface_destroy_listener);
+ ivisurf->surface = NULL;
+ ivisurf->view = NULL;
+}
+
+/**
+ * Internal API to check layer/surface already added in layer/screen.
+ * Called by weston_layout_layerAddSurface/weston_layout_screenAddLayer
+ */
+static int
+is_surface_in_layer(struct weston_layout_surface *ivisurf,
+ struct weston_layout_layer *ivilayer)
+{
+ struct weston_layout_surface *surf = NULL;
+
+ wl_list_for_each(surf, &ivilayer->pending.list_surface, pending.link) {
+ if (surf->id_surface == ivisurf->id_surface) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+is_layer_in_screen(struct weston_layout_layer *ivilayer,
+ struct weston_layout_screen *iviscrn)
+{
+ struct weston_layout_layer *layer = NULL;
+
+ wl_list_for_each(layer, &iviscrn->pending.list_layer, pending.link) {
+ if (layer->id_layer == ivilayer->id_layer) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Internal API to initialize screens found from output_list of weston_compositor.
+ * Called by weston_layout_initWithCompositor.
+ */
+static void
+create_screen(struct weston_compositor *ec)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_screen *iviscrn = NULL;
+ struct weston_output *output = NULL;
+ int32_t count = 0;
+
+ wl_list_for_each(output, &ec->output_list, link) {
+ iviscrn = calloc(1, sizeof *iviscrn);
+ if (iviscrn == NULL) {
+ weston_log("fails to allocate memory\n");
+ continue;
+ }
+
+ wl_list_init(&iviscrn->link);
+ iviscrn->layout = layout;
+
+ iviscrn->id_screen = count;
+ count++;
+
+ iviscrn->output = output;
+ iviscrn->event_mask = 0;
+
+ wl_list_init(&iviscrn->pending.list_layer);
+ wl_list_init(&iviscrn->pending.link);
+
+ wl_list_init(&iviscrn->order.list_layer);
+ wl_list_init(&iviscrn->order.link);
+
+ wl_list_insert(&layout->list_screen, &iviscrn->link);
+ }
+}
+
+/**
+ * Internal APIs to initialize properties of surface/layer when they are created.
+ */
+static void
+init_layerProperties(struct weston_layout_LayerProperties *prop,
+ int32_t width, int32_t height)
+{
+ memset(prop, 0, sizeof *prop);
+ prop->opacity = wl_fixed_from_double(1.0);
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+ prop->destWidth = width;
+ prop->destHeight = height;
+}
+
+static void
+init_surfaceProperties(struct weston_layout_SurfaceProperties *prop)
+{
+ memset(prop, 0, sizeof *prop);
+ prop->opacity = wl_fixed_from_double(1.0);
+}
+
+/**
+ * Internal APIs to be called from weston_layout_commitChanges.
+ */
+static void
+update_opacity(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ double layer_alpha = wl_fixed_to_double(ivilayer->prop.opacity);
+ double surf_alpha = wl_fixed_to_double(ivisurf->prop.opacity);
+
+ if ((ivilayer->event_mask & IVI_NOTIFICATION_OPACITY) ||
+ (ivisurf->event_mask & IVI_NOTIFICATION_OPACITY)) {
+ if (ivisurf->view == NULL) {
+ return;
+ }
+ ivisurf->view->alpha = layer_alpha * surf_alpha;
+ }
+}
+
+static void
+update_surface_orientation(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->surface_rotation.matrix;
+ float width = 0.0f;
+ float height = 0.0f;
+ float v_sin = 0.0f;
+ float v_cos = 0.0f;
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float sx = 1.0f;
+ float sy = 1.0f;
+
+ if (view == NULL) {
+ return;
+ }
+
+ if ((ivilayer->prop.destWidth == 0) ||
+ (ivilayer->prop.destHeight == 0)) {
+ return;
+ }
+ width = (float)ivilayer->prop.destWidth;
+ height = (float)ivilayer->prop.destHeight;
+
+ switch (ivisurf->prop.orientation) {
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_0_DEGREES:
+ v_sin = 0.0f;
+ v_cos = 1.0f;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_90_DEGREES:
+ v_sin = 1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_180_DEGREES:
+ v_sin = 0.0f;
+ v_cos = -1.0f;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_270_DEGREES:
+ default:
+ v_sin = -1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ }
+ wl_list_remove(&ivisurf->surface_rotation.link);
+ weston_view_geometry_dirty(view);
+
+ weston_matrix_init(matrix);
+ cx = 0.5f * width;
+ cy = 0.5f * height;
+ weston_matrix_translate(matrix, -cx, -cy, 0.0f);
+ weston_matrix_rotate_xy(matrix, v_cos, v_sin);
+ weston_matrix_scale(matrix, sx, sy, 1.0);
+ weston_matrix_translate(matrix, cx, cy, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->surface_rotation.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_layer_orientation(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_surface *es = ivisurf->surface;
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->layer_rotation.matrix;
+ struct weston_output *output = NULL;
+ float width = 0.0f;
+ float height = 0.0f;
+ float v_sin = 0.0f;
+ float v_cos = 0.0f;
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float sx = 1.0f;
+ float sy = 1.0f;
+
+ if (es == NULL || view == NULL) {
+ return;
+ }
+
+ output = es->output;
+ if (output == NULL) {
+ return;
+ }
+ if ((output->width == 0) || (output->height == 0)) {
+ return;
+ }
+ width = (float)output->width;
+ height = (float)output->height;
+
+ switch (ivilayer->prop.orientation) {
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_0_DEGREES:
+ v_sin = 0.0f;
+ v_cos = 1.0f;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_90_DEGREES:
+ v_sin = 1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_180_DEGREES:
+ v_sin = 0.0f;
+ v_cos = -1.0f;
+ break;
+ case WESTON_LAYOUT_SURFACE_ORIENTATION_270_DEGREES:
+ default:
+ v_sin = -1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ }
+ wl_list_remove(&ivisurf->layer_rotation.link);
+ weston_view_geometry_dirty(view);
+
+ weston_matrix_init(matrix);
+ cx = 0.5f * width;
+ cy = 0.5f * height;
+ weston_matrix_translate(matrix, -cx, -cy, 0.0f);
+ weston_matrix_rotate_xy(matrix, v_cos, v_sin);
+ weston_matrix_scale(matrix, sx, sy, 1.0);
+ weston_matrix_translate(matrix, cx, cy, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->layer_rotation.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_surface_position(struct weston_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ float tx = (float)ivisurf->prop.destX;
+ float ty = (float)ivisurf->prop.destY;
+ struct weston_matrix *matrix = &ivisurf->surface_pos.matrix;
+
+ if (view == NULL) {
+ return;
+ }
+
+ wl_list_remove(&ivisurf->surface_pos.link);
+
+ weston_matrix_init(matrix);
+ weston_matrix_translate(matrix, tx, ty, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->surface_pos.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+
+#if 0
+ /* disable zoom animation */
+ weston_zoom_run(es, 0.0, 1.0, NULL, NULL);
+#endif
+
+}
+
+static void
+update_layer_position(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->layer_pos.matrix;
+ float tx = (float)ivilayer->prop.destX;
+ float ty = (float)ivilayer->prop.destY;
+
+ if (view == NULL) {
+ return;
+ }
+
+ wl_list_remove(&ivisurf->layer_pos.link);
+
+ weston_matrix_init(matrix);
+ weston_matrix_translate(matrix, tx, ty, 0.0f);
+ wl_list_insert(
+ &view->geometry.transformation_list,
+ &ivisurf->layer_pos.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_scale(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->scaling.matrix;
+ float sx = 0.0f;
+ float sy = 0.0f;
+ float lw = 0.0f;
+ float sw = 0.0f;
+ float lh = 0.0f;
+ float sh = 0.0f;
+
+ if (view == NULL) {
+ return;
+ }
+
+ if (ivisurf->prop.sourceWidth == 0 && ivisurf->prop.sourceHeight == 0) {
+ ivisurf->prop.sourceWidth = ivisurf->buffer_width;
+ ivisurf->prop.sourceHeight = ivisurf->buffer_height;
+
+ if (ivisurf->prop.destWidth == 0 && ivisurf->prop.destHeight == 0) {
+ ivisurf->prop.destWidth = ivisurf->buffer_width;
+ ivisurf->prop.destHeight = ivisurf->buffer_height;
+ }
+ }
+
+ lw = ((float)ivilayer->prop.destWidth / ivilayer->prop.sourceWidth );
+ sw = ((float)ivisurf->prop.destWidth / ivisurf->prop.sourceWidth );
+ lh = ((float)ivilayer->prop.destHeight / ivilayer->prop.sourceHeight);
+ sh = ((float)ivisurf->prop.destHeight / ivisurf->prop.sourceHeight );
+ sx = sw * lw;
+ sy = sh * lh;
+
+ wl_list_remove(&ivisurf->scaling.link);
+ weston_matrix_init(matrix);
+ weston_matrix_scale(matrix, sx, sy, 1.0f);
+
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->scaling.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_prop(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *ivisurf)
+{
+ if (ivilayer->event_mask | ivisurf->event_mask) {
+ update_opacity(ivilayer, ivisurf);
+ update_layer_orientation(ivilayer, ivisurf);
+ update_layer_position(ivilayer, ivisurf);
+ update_surface_position(ivisurf);
+ update_surface_orientation(ivilayer, ivisurf);
+ update_scale(ivilayer, ivisurf);
+
+ ivisurf->update_count++;
+
+ if (ivisurf->view != NULL) {
+ weston_view_geometry_dirty(ivisurf->view);
+ }
+
+ if (ivisurf->surface != NULL) {
+ weston_surface_damage(ivisurf->surface);
+ }
+ }
+}
+
+static void
+commit_changes(struct weston_layout *layout)
+{
+ struct weston_layout_screen *iviscrn = NULL;
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, order.link) {
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, order.link) {
+ update_prop(ivilayer, ivisurf);
+ }
+ }
+ }
+}
+
+static void
+commit_list_surface(struct weston_layout *layout)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ ivisurf->prop = ivisurf->pending.prop;
+ }
+}
+
+static void
+commit_list_layer(struct weston_layout *layout)
+{
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_surface *next = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ ivilayer->prop = ivilayer->pending.prop;
+
+ if (!(ivilayer->event_mask &
+ (IVI_NOTIFICATION_ADD | IVI_NOTIFICATION_REMOVE)) ) {
+ continue;
+ }
+
+ wl_list_for_each_safe(ivisurf, next,
+ &ivilayer->order.list_surface, order.link) {
+ remove_ordersurface_from_layer(ivisurf);
+
+ if (!wl_list_empty(&ivisurf->order.link)) {
+ wl_list_remove(&ivisurf->order.link);
+ }
+
+ wl_list_init(&ivisurf->order.link);
+ }
+
+ wl_list_init(&ivilayer->order.list_surface);
+ wl_list_for_each(ivisurf, &ivilayer->pending.list_surface,
+ pending.link) {
+ if(!wl_list_empty(&ivisurf->order.link)){
+ wl_list_remove(&ivisurf->order.link);
+ wl_list_init(&ivisurf->order.link);
+ }
+
+ wl_list_insert(&ivilayer->order.list_surface,
+ &ivisurf->order.link);
+ add_ordersurface_to_layer(ivisurf, ivilayer);
+ }
+ }
+}
+
+static void
+commit_list_screen(struct weston_layout *layout)
+{
+ struct weston_compositor *ec = layout->compositor;
+ struct weston_layout_screen *iviscrn = NULL;
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_layer *next = NULL;
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ if (iviscrn->event_mask & IVI_NOTIFICATION_ADD) {
+ wl_list_for_each_safe(ivilayer, next,
+ &iviscrn->order.list_layer, order.link) {
+ remove_orderlayer_from_screen(ivilayer);
+
+ if (!wl_list_empty(&ivilayer->order.link)) {
+ wl_list_remove(&ivilayer->order.link);
+ }
+
+ wl_list_init(&ivilayer->order.link);
+ }
+
+ wl_list_init(&iviscrn->order.list_layer);
+ wl_list_for_each(ivilayer, &iviscrn->pending.list_layer,
+ pending.link) {
+ wl_list_insert(&iviscrn->order.list_layer,
+ &ivilayer->order.link);
+ add_orderlayer_to_screen(ivilayer, iviscrn);
+ }
+ iviscrn->event_mask = 0;
+ }
+
+ /* For rendering */
+ wl_list_init(&ec->layer_list);
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, order.link) {
+ if (ivilayer->prop.visibility == 0) {
+ continue;
+ }
+
+ wl_list_insert(&ec->layer_list, &ivilayer->el.link);
+ wl_list_init(&ivilayer->el.view_list);
+
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, order.link) {
+ if (ivisurf->prop.visibility == 0) {
+ continue;
+ }
+
+ if (ivisurf->surface == NULL || ivisurf->view == NULL) {
+ continue;
+ }
+
+ wl_list_insert(&ivilayer->el.view_list,
+ &ivisurf->view->layer_link);
+ ivisurf->surface->output = iviscrn->output;
+ }
+ }
+
+ /*Add cursor layer if cursor is configured.*/
+ if (layout->is_cursor_enabled) {
+ wl_list_insert(&ec->layer_list, &ec->cursor_layer.link);
+ }
+
+ break;
+ }
+}
+
+static void
+send_surface_prop(struct weston_layout_surface *ivisurf)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+
+ wl_list_for_each(notification, &ivisurf->list_notification, link) {
+ notification->callback(ivisurf, &ivisurf->prop,
+ ivisurf->event_mask,
+ notification->userdata);
+ }
+
+ ivisurf->event_mask = 0;
+}
+
+static void
+send_layer_prop(struct weston_layout_layer *ivilayer)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+
+ wl_list_for_each(notification, &ivilayer->list_notification, link) {
+ notification->callback(ivilayer, &ivilayer->prop,
+ ivilayer->event_mask,
+ notification->userdata);
+ }
+
+ ivilayer->event_mask = 0;
+}
+
+static void
+send_prop(struct weston_layout *layout)
+{
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ send_layer_prop(ivilayer);
+ }
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ send_surface_prop(ivisurf);
+ }
+}
+
+/**
+ * Exported APIs of weston-layout library are implemented from here.
+ * Brief of APIs is described in weston-layout.h.
+ */
+WL_EXPORT struct weston_view *
+weston_layout_get_weston_view(struct weston_layout_surface *surface)
+{
+ return (surface != NULL) ? surface->view : NULL;
+}
+
+WL_EXPORT void
+weston_layout_initWithCompositor(struct weston_compositor *ec)
+{
+ struct weston_layout *layout = get_instance();
+
+ layout->compositor = ec;
+
+ wl_list_init(&layout->list_surface);
+ wl_list_init(&layout->list_layer);
+ wl_list_init(&layout->list_screen);
+
+ wl_list_init(&layout->layer_notification.list_create);
+ wl_list_init(&layout->layer_notification.list_remove);
+
+ wl_list_init(&layout->surface_notification.list_create);
+ wl_list_init(&layout->surface_notification.list_remove);
+ wl_list_init(&layout->surface_notification.list_configure);
+
+ create_screen(ec);
+
+ struct weston_config *config = weston_config_parse("weston.ini");
+ struct weston_config_section *s =
+ weston_config_get_section(config, "ivi-shell", NULL, NULL);
+
+ /*A cursor is configured if weston.ini has keys.*/
+ char* cursor_theme = NULL;
+ weston_config_section_get_string(s, "cursor-theme", &cursor_theme, NULL);
+ layout->is_cursor_enabled = (NULL != cursor_theme);
+ free(cursor_theme);
+ weston_config_destroy(config);
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationCreateLayer(layerCreateNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_layerCreateNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationCreateLayer: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->layer_notification.list_create, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationRemoveLayer(layerRemoveNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_layerRemoveNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationRemoveLayer: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->layer_notification.list_remove, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationCreateSurface(surfaceCreateNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationCreateSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_create, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationRemoveSurface(surfaceRemoveNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceRemoveNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationRemoveSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_remove, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_setNotificationConfigureSurface(surfaceConfigureNotificationFunc callback,
+ void *userdata)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceConfigureNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("weston_layout_setNotificationConfigureSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_configure, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT uint32_t
+weston_layout_getIdOfSurface(struct weston_layout_surface *ivisurf)
+{
+ return ivisurf->id_surface;
+}
+
+WL_EXPORT uint32_t
+weston_layout_getIdOfLayer(struct weston_layout_layer *ivilayer)
+{
+ return ivilayer->id_layer;
+}
+
+WL_EXPORT struct weston_layout_layer *
+weston_layout_getLayerFromId(uint32_t id_layer)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ if (ivilayer->id_layer == id_layer) {
+ return ivilayer;
+ }
+ }
+
+ return NULL;
+}
+
+WL_EXPORT struct weston_layout_surface *
+weston_layout_getSurfaceFromId(uint32_t id_surface)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+WL_EXPORT struct weston_layout_screen *
+weston_layout_getScreenFromId(uint32_t id_screen)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_screen *iviscrn = NULL;
+ (void)id_screen;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+//FIXME : select iviscrn from list_screen by id_screen
+ return iviscrn;
+ break;
+ }
+
+ return NULL;
+}
+
+WL_EXPORT int32_t
+weston_layout_getScreenResolution(struct weston_layout_screen *iviscrn,
+ uint32_t *pWidth, uint32_t *pHeight)
+{
+ struct weston_output *output = NULL;
+
+ if (pWidth == NULL || pHeight == NULL) {
+ weston_log("weston_layout_getScreenResolution: invalid argument\n");
+ return -1;
+ }
+
+ output = iviscrn->output;
+ *pWidth = output->current_mode->width;
+ *pHeight = output->current_mode->height;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceAddNotification(struct weston_layout_surface *ivisurf,
+ surfacePropertyNotificationFunc callback,
+ void *userdata)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+
+ if (ivisurf == NULL || callback == NULL) {
+ weston_log("weston_layout_surfaceAddNotification: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&ivisurf->list_notification, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceRemoveNotification(struct weston_layout_surface *ivisurf)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+ struct link_surfacePropertyNotification *next = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceRemoveNotification: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(notification, next,
+ &ivisurf->list_notification, link) {
+ if (!wl_list_empty(&notification->link)) {
+ wl_list_remove(&notification->link);
+ }
+ free(notification);
+ }
+ wl_list_init(&ivisurf->list_notification);
+
+ return 0;
+}
+
+WL_EXPORT struct weston_layout_surface*
+weston_layout_surfaceCreate(struct weston_surface *wl_surface,
+ uint32_t id_surface)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ if (wl_surface == NULL) {
+ weston_log("weston_layout_surfaceCreate: invalid argument\n");
+ return NULL;
+ }
+
+ ivisurf = get_surface(&layout->list_surface, id_surface);
+ if (ivisurf != NULL) {
+ if (ivisurf->surface != NULL) {
+ weston_log("id_surface(%d) is already created\n", id_surface);
+ return NULL;
+ } else {
+ /* if ivisurf->surface exist, wl_surface is tied to id_surface again */
+ /* This means client destroys ivi_surface once, and then tries to tie
+ the id_surface to new wl_surface again. The property of id_surface can
+ be inherited.
+ */
+ weston_layout_surfaceSetNativeContent(
+ wl_surface, wl_surface->width, wl_surface->height, id_surface);
+ return ivisurf;
+ }
+ }
+
+ ivisurf = calloc(1, sizeof *ivisurf);
+ if (ivisurf == NULL) {
+ weston_log("fails to allocate memory\n");
+ return NULL;
+ }
+
+ wl_list_init(&ivisurf->link);
+ wl_list_init(&ivisurf->list_notification);
+ wl_list_init(&ivisurf->list_layer);
+ ivisurf->id_surface = id_surface;
+ ivisurf->layout = layout;
+
+ ivisurf->surface = wl_surface;
+ ivisurf->surface_destroy_listener.notify =
+ westonsurface_destroy_from_ivisurface;
+ wl_resource_add_destroy_listener(wl_surface->resource,
+ &ivisurf->surface_destroy_listener);
+
+ ivisurf->view = weston_view_create(wl_surface);
+ if (ivisurf->view == NULL) {
+ weston_log("fails to allocate memory\n");
+ }
+
+ ivisurf->buffer_width = 0;
+ ivisurf->buffer_height = 0;
+
+ wl_list_init(&ivisurf->surface_rotation.link);
+ wl_list_init(&ivisurf->layer_rotation.link);
+ wl_list_init(&ivisurf->surface_pos.link);
+ wl_list_init(&ivisurf->layer_pos.link);
+ wl_list_init(&ivisurf->scaling.link);
+
+ init_surfaceProperties(&ivisurf->prop);
+ ivisurf->pixelformat = WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_8888;
+ ivisurf->event_mask = 0;
+
+ ivisurf->pending.prop = ivisurf->prop;
+ wl_list_init(&ivisurf->pending.link);
+
+ wl_list_init(&ivisurf->order.link);
+ wl_list_init(&ivisurf->order.list_layer);
+
+ wl_list_insert(&layout->list_surface, &ivisurf->link);
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ return ivisurf;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetNativeContent(struct weston_surface *surface,
+ uint32_t width,
+ uint32_t height,
+ uint32_t id_surface)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf;
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ ivisurf = get_surface(&layout->list_surface, id_surface);
+ if (ivisurf == NULL) {
+ weston_log("layout surface is not found\n");
+ return -1;
+ }
+
+ if (ivisurf->surface != NULL) {
+ if (surface != NULL) {
+ weston_log("id_surface(%d) is already set the native content\n",
+ id_surface);
+ return -1;
+ }
+
+ wl_list_remove(&ivisurf->surface_destroy_listener.link);
+ weston_view_destroy(ivisurf->view);
+
+ ivisurf->surface = NULL;
+ ivisurf->view = NULL;
+ }
+
+ if (surface == NULL)
+ return 0;
+
+ ivisurf->surface = surface;
+ ivisurf->surface_destroy_listener.notify =
+ westonsurface_destroy_from_ivisurface;
+ wl_resource_add_destroy_listener(surface->resource,
+ &ivisurf->surface_destroy_listener);
+ ivisurf->view = weston_view_create(surface);
+ if (ivisurf->view == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ ivisurf->buffer_width = width;
+ ivisurf->buffer_height = height;
+ ivisurf->pixelformat = WESTON_LAYOUT_SURFACE_PIXELFORMAT_RGBA_8888;
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ return 0;
+}
+
+WL_EXPORT void
+weston_layout_surfaceConfigure(struct weston_layout_surface *ivisurf,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ ivisurf->buffer_width = width;
+ ivisurf->buffer_height = height;
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_configure, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceRemove(struct weston_layout_surface *ivisurf)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_surfaceRemoveNotification *notification = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceRemove: invalid argument\n");
+ return -1;
+ }
+
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ if (!wl_list_empty(&ivisurf->order.link)) {
+ wl_list_remove(&ivisurf->order.link);
+ }
+ if (!wl_list_empty(&ivisurf->link)) {
+ wl_list_remove(&ivisurf->link);
+ }
+ remove_ordersurface_from_layer(ivisurf);
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_remove, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ free(ivisurf);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_UpdateInputEventAcceptanceOn(struct weston_layout_surface *ivisurf,
+ uint32_t devices, uint32_t acceptance)
+{
+ /* not supported */
+ (void)ivisurf;
+ (void)devices;
+ (void)acceptance;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceInitialize(struct weston_layout_surface **pSurfaceId)
+{
+ /* not supported */
+ (void)pSurfaceId;
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getPropertiesOfLayer(struct weston_layout_layer *ivilayer,
+ struct weston_layout_LayerProperties *pLayerProperties)
+{
+ if (ivilayer == NULL || pLayerProperties == NULL) {
+ weston_log("weston_layout_getPropertiesOfLayer: invalid argument\n");
+ return -1;
+ }
+
+ *pLayerProperties = ivilayer->prop;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getNumberOfHardwareLayers(uint32_t id_screen,
+ uint32_t *pNumberOfHardwareLayers)
+{
+ /* not supported */
+ (void)id_screen;
+ (void)pNumberOfHardwareLayers;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getScreens(uint32_t *pLength, weston_layout_screen_ptr **ppArray)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_screen *iviscrn = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getScreens: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_screen);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_screen_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ (*ppArray)[n++] = iviscrn;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getScreensUnderLayer(struct weston_layout_layer *ivilayer,
+ uint32_t *pLength,
+ weston_layout_screen_ptr **ppArray)
+{
+ struct link_screen *link_scrn = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getScreensUnderLayer: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivilayer->list_screen);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_screen_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(link_scrn, &ivilayer->list_screen, link) {
+ (*ppArray)[n++] = link_scrn->iviscrn;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getLayers(uint32_t *pLength, weston_layout_layer_ptr **ppArray)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getLayers: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ (*ppArray)[n++] = ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getLayersOnScreen(struct weston_layout_screen *iviscrn,
+ uint32_t *pLength,
+ weston_layout_layer_ptr **ppArray)
+{
+ struct weston_layout_layer *ivilayer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (iviscrn == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getLayersOnScreen: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&iviscrn->order.list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, link) {
+ (*ppArray)[n++] = ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getLayersUnderSurface(struct weston_layout_surface *ivisurf,
+ uint32_t *pLength,
+ weston_layout_layer_ptr **ppArray)
+{
+ struct link_layer *link_layer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivisurf == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getLayers: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivisurf->list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(link_layer, &ivisurf->list_layer, link) {
+ (*ppArray)[n++] = link_layer->ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getSurfaces(uint32_t *pLength, weston_layout_surface_ptr **ppArray)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getSurfaces: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_surface);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_surface_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ (*ppArray)[n++] = ivisurf;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getSurfacesOnLayer(struct weston_layout_layer *ivilayer,
+ uint32_t *pLength,
+ weston_layout_surface_ptr **ppArray)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("weston_layout_getSurfaceIDsOnLayer: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivilayer->order.list_surface);
+
+ if (length != 0) {
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(weston_layout_surface_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, order.link) {
+ (*ppArray)[n++] = ivisurf;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT struct weston_layout_layer *
+weston_layout_layerCreateWithDimension(uint32_t id_layer,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+ struct link_layerCreateNotification *notification = NULL;
+
+ ivilayer = get_layer(&layout->list_layer, id_layer);
+ if (ivilayer != NULL) {
+ weston_log("id_layer is already created\n");
+ return ivilayer;
+ }
+
+ ivilayer = calloc(1, sizeof *ivilayer);
+ if (ivilayer == NULL) {
+ weston_log("fails to allocate memory\n");
+ return NULL;
+ }
+
+ wl_list_init(&ivilayer->link);
+ wl_list_init(&ivilayer->list_notification);
+ wl_list_init(&ivilayer->list_screen);
+ ivilayer->layout = layout;
+ ivilayer->id_layer = id_layer;
+
+ init_layerProperties(&ivilayer->prop, width, height);
+ ivilayer->event_mask = 0;
+
+ wl_list_init(&ivilayer->pending.list_surface);
+ wl_list_init(&ivilayer->pending.link);
+ ivilayer->pending.prop = ivilayer->prop;
+
+ wl_list_init(&ivilayer->order.list_surface);
+ wl_list_init(&ivilayer->order.link);
+
+ wl_list_insert(&layout->list_layer, &ivilayer->link);
+
+ wl_list_for_each(notification,
+ &layout->layer_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivilayer, notification->userdata);
+ }
+ }
+
+ return ivilayer;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerRemove(struct weston_layout_layer *ivilayer)
+{
+ struct weston_layout *layout = get_instance();
+ struct link_layerRemoveNotification *notification = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerRemove: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each(notification,
+ &layout->layer_notification.list_remove, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivilayer, notification->userdata);
+ }
+ }
+
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ if (!wl_list_empty(&ivilayer->order.link)) {
+ wl_list_remove(&ivilayer->order.link);
+ }
+ if (!wl_list_empty(&ivilayer->link)) {
+ wl_list_remove(&ivilayer->link);
+ }
+ remove_orderlayer_from_screen(ivilayer);
+
+ free(ivilayer);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetType(struct weston_layout_layer *ivilayer,
+ uint32_t *pLayerType)
+{
+ /* not supported */
+ (void)ivilayer;
+ (void)pLayerType;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetVisibility(struct weston_layout_layer *ivilayer,
+ uint32_t newVisibility)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->visibility = newVisibility;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_VISIBILITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetVisibility(struct weston_layout_layer *ivilayer, uint32_t *pVisibility)
+{
+ if (ivilayer == NULL || pVisibility == NULL) {
+ weston_log("weston_layout_layerGetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ *pVisibility = ivilayer->prop.visibility;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetOpacity(struct weston_layout_layer *ivilayer,
+ float opacity)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->opacity = opacity;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_OPACITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetOpacity(struct weston_layout_layer *ivilayer,
+ float *pOpacity)
+{
+ if (ivilayer == NULL || pOpacity == NULL) {
+ weston_log("weston_layout_layerGetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ *pOpacity = ivilayer->prop.opacity;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetSourceRectangle(struct weston_layout_layer *ivilayer,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetSourceRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->sourceX = x;
+ prop->sourceY = y;
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetDestinationRectangle(struct weston_layout_layer *ivilayer,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetDestinationRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->destX = x;
+ prop->destY = y;
+ prop->destWidth = width;
+ prop->destHeight = height;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_DEST_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetDimension(struct weston_layout_layer *ivilayer,
+ uint32_t *pDimension)
+{
+ if (ivilayer == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("weston_layout_layerGetDimension: invalid argument\n");
+ return -1;
+ }
+
+ pDimension[0] = ivilayer->prop.destX;
+ pDimension[1] = ivilayer->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetDimension(struct weston_layout_layer *ivilayer,
+ uint32_t *pDimension)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("weston_layout_layerSetDimension: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+
+ prop->destWidth = pDimension[0];
+ prop->destHeight = pDimension[1];
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_DIMENSION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetPosition(struct weston_layout_layer *ivilayer, int32_t *pPosition)
+{
+ if (ivilayer == NULL || pPosition == NULL) {
+ weston_log("weston_layout_layerGetPosition: invalid argument\n");
+ return -1;
+ }
+
+ pPosition[0] = ivilayer->prop.destX;
+ pPosition[1] = ivilayer->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetPosition(struct weston_layout_layer *ivilayer, int32_t *pPosition)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL || pPosition == NULL) {
+ weston_log("weston_layout_layerSetPosition: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->destX = pPosition[0];
+ prop->destY = pPosition[1];
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_POSITION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetOrientation(struct weston_layout_layer *ivilayer,
+ uint32_t orientation)
+{
+ struct weston_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->orientation = orientation;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ORIENTATION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetOrientation(struct weston_layout_layer *ivilayer,
+ uint32_t *pOrientation)
+{
+ if (ivilayer == NULL || pOrientation == NULL) {
+ weston_log("weston_layout_layerGetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ *pOrientation = ivilayer->prop.orientation;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetChromaKey(struct weston_layout_layer *ivilayer, uint32_t* pColor)
+{
+ /* not supported */
+ (void)ivilayer;
+ (void)pColor;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerSetRenderOrder(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface **pSurface,
+ uint32_t number)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+ uint32_t *id_surface = NULL;
+ uint32_t i = 0;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerSetRenderOrder: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_init(&ivilayer->pending.list_surface);
+
+ if (pSurface == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < number; i++) {
+ id_surface = &pSurface[i]->id_surface;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ if (*id_surface != ivisurf->id_surface) {
+ continue;
+ }
+
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ wl_list_insert(&ivilayer->pending.list_surface,
+ &ivisurf->pending.link);
+ break;
+ }
+ }
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerGetCapabilities(struct weston_layout_layer *ivilayer,
+ uint32_t *pCapabilities)
+{
+ /* not supported */
+ (void)ivilayer;
+ (void)pCapabilities;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerTypeGetCapabilities(uint32_t layerType,
+ uint32_t *pCapabilities)
+{
+ /* not supported */
+ (void)layerType;
+ (void)pCapabilities;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetVisibility(struct weston_layout_surface *ivisurf,
+ uint32_t newVisibility)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->visibility = newVisibility;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_VISIBILITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetVisibility(struct weston_layout_surface *ivisurf,
+ uint32_t *pVisibility)
+{
+ if (ivisurf == NULL || pVisibility == NULL) {
+ weston_log("weston_layout_surfaceGetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ *pVisibility = ivisurf->prop.visibility;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetOpacity(struct weston_layout_surface *ivisurf,
+ float opacity)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->opacity = opacity;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_OPACITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetOpacity(struct weston_layout_surface *ivisurf,
+ float *pOpacity)
+{
+ if (ivisurf == NULL || pOpacity == NULL) {
+ weston_log("weston_layout_surfaceGetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ *pOpacity = ivisurf->prop.opacity;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_SetKeyboardFocusOn(struct weston_layout_surface *ivisurf)
+{
+ /* not supported */
+ (void)ivisurf;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_GetKeyboardFocusSurfaceId(struct weston_layout_surface **pSurfaceId)
+{
+ /* not supported */
+ (void)pSurfaceId;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetDestinationRectangle(struct weston_layout_surface *ivisurf,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetDestinationRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destX = x;
+ prop->destY = y;
+ prop->destWidth = width;
+ prop->destHeight = height;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_DEST_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetDimension(struct weston_layout_surface *ivisurf, uint32_t *pDimension)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("weston_layout_surfaceSetDimension: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destWidth = pDimension[0];
+ prop->destHeight = pDimension[1];
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_DIMENSION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetDimension(struct weston_layout_surface *ivisurf,
+ uint32_t *pDimension)
+{
+ if (ivisurf == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("weston_layout_surfaceGetDimension: invalid argument\n");
+ return -1;
+ }
+
+ pDimension[0] = ivisurf->prop.destWidth;
+ pDimension[1] = ivisurf->prop.destHeight;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetPosition(struct weston_layout_surface *ivisurf,
+ int32_t *pPosition)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL || pPosition == NULL) {
+ weston_log("weston_layout_surfaceSetPosition: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destX = pPosition[0];
+ prop->destY = pPosition[1];
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_POSITION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetPosition(struct weston_layout_surface *ivisurf,
+ int32_t *pPosition)
+{
+ if (ivisurf == NULL || pPosition == NULL) {
+ weston_log("weston_layout_surfaceGetPosition: invalid argument\n");
+ return -1;
+ }
+
+ pPosition[0] = ivisurf->prop.destX;
+ pPosition[1] = ivisurf->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetOrientation(struct weston_layout_surface *ivisurf,
+ uint32_t orientation)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->orientation = orientation;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_ORIENTATION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetOrientation(struct weston_layout_surface *ivisurf,
+ uint32_t *pOrientation)
+{
+ if (ivisurf == NULL || pOrientation == NULL) {
+ weston_log("weston_layout_surfaceGetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ *pOrientation = ivisurf->prop.orientation;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceGetPixelformat(struct weston_layout_layer *ivisurf, uint32_t *pPixelformat)
+{
+ /* not supported */
+ (void)ivisurf;
+ (void)pPixelformat;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetChromaKey(struct weston_layout_surface *ivisurf, uint32_t* pColor)
+{
+ /* not supported */
+ (void)ivisurf;
+ (void)pColor;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_screenAddLayer(struct weston_layout_screen *iviscrn,
+ struct weston_layout_layer *addlayer)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+ struct weston_layout_layer *next = NULL;
+ int is_layer_in_scrn = 0;
+
+ if (iviscrn == NULL || addlayer == NULL) {
+ weston_log("weston_layout_screenAddLayer: invalid argument\n");
+ return -1;
+ }
+
+ is_layer_in_scrn = is_layer_in_screen(addlayer, iviscrn);
+ if (is_layer_in_scrn == 1) {
+ weston_log("weston_layout_screenAddLayer: addlayer is already available\n");
+ return 0;
+ }
+
+ wl_list_for_each_safe(ivilayer, next, &layout->list_layer, link) {
+ if (ivilayer->id_layer == addlayer->id_layer) {
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ wl_list_init(&ivilayer->pending.link);
+ wl_list_insert(&iviscrn->pending.list_layer,
+ &ivilayer->pending.link);
+ break;
+ }
+ }
+
+ iviscrn->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_screenSetRenderOrder(struct weston_layout_screen *iviscrn,
+ struct weston_layout_layer **pLayer,
+ const uint32_t number)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_layer *ivilayer = NULL;
+ uint32_t *id_layer = NULL;
+ uint32_t i = 0;
+
+ if (iviscrn == NULL) {
+ weston_log("weston_layout_screenSetRenderOrder: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_init(&iviscrn->pending.list_layer);
+
+ if (pLayer == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < number; i++) {
+ id_layer = &pLayer[i]->id_layer;
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ if (*id_layer == ivilayer->id_layer) {
+ continue;
+ }
+
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ wl_list_init(&ivilayer->pending.link);
+ wl_list_insert(&iviscrn->pending.list_layer,
+ &ivilayer->pending.link);
+ break;
+ }
+ }
+
+ iviscrn->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_takeScreenshot(struct weston_layout_screen *iviscrn,
+ const char *filename)
+{
+ struct weston_output *output = NULL;
+ cairo_surface_t *cairo_surf = NULL;
+ int32_t i = 0;
+ int32_t width = 0;
+ int32_t height = 0;
+ int32_t stride = 0;
+ uint8_t *readpixs = NULL;
+ uint8_t *writepixs = NULL;
+ uint8_t *d = NULL;
+ uint8_t *s = NULL;
+
+ if (iviscrn == NULL || filename == NULL) {
+ weston_log("weston_layout_takeScreenshot: invalid argument\n");
+ return -1;
+ }
+
+ output = iviscrn->output;
+ output->disable_planes--;
+
+ width = output->current_mode->width;
+ height = output->current_mode->height;
+ stride = width * (PIXMAN_FORMAT_BPP(output->compositor->read_format) / 8);
+
+ readpixs = malloc(stride * height);
+ if (readpixs == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+ writepixs = malloc(stride * height);
+ if (writepixs == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ output->compositor->renderer->read_pixels(output,
+ output->compositor->read_format, readpixs,
+ 0, 0, width, height);
+
+ s = readpixs;
+ d = writepixs + stride * (height - 1);
+
+ for (i = 0; i < height; i++) {
+ memcpy(d, s, stride);
+ d -= stride;
+ s += stride;
+ }
+
+ cairo_surf = cairo_image_surface_create_for_data(writepixs,
+ CAIRO_FORMAT_ARGB32,
+ width, height, stride);
+ cairo_surface_write_to_png(cairo_surf, filename);
+ cairo_surface_destroy(cairo_surf);
+ free(writepixs);
+ free(readpixs);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_takeLayerScreenshot(const char *filename, struct weston_layout_layer *ivilayer)
+{
+ /* not supported */
+ (void)filename;
+ (void)ivilayer;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_takeSurfaceScreenshot(const char *filename,
+ struct weston_layout_surface *ivisurf)
+{
+ weston_log("weston_layout_takeSurfaceScreenshot: "
+ "This function is not supported now\n");
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_SetOptimizationMode(uint32_t id, uint32_t mode)
+{
+ /* not supported */
+ (void)id;
+ (void)mode;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_GetOptimizationMode(uint32_t id, uint32_t *pMode)
+{
+ /* not supported */
+ (void)id;
+ (void)pMode;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerAddNotification(struct weston_layout_layer *ivilayer,
+ layerPropertyNotificationFunc callback,
+ void *userdata)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+
+ if (ivilayer == NULL || callback == NULL) {
+ weston_log("weston_layout_layerAddNotification: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&ivilayer->list_notification, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerRemoveNotification(struct weston_layout_layer *ivilayer)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+ struct link_layerPropertyNotification *next = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("weston_layout_layerRemoveNotification: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(notification, next,
+ &ivilayer->list_notification, link) {
+ if (!wl_list_empty(&notification->link)) {
+ wl_list_remove(&notification->link);
+ }
+ free(notification);
+ }
+ wl_list_init(&ivilayer->list_notification);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_getPropertiesOfSurface(struct weston_layout_surface *ivisurf,
+ struct weston_layout_SurfaceProperties *pSurfaceProperties)
+{
+ if (ivisurf == NULL || pSurfaceProperties == NULL) {
+ weston_log("weston_layout_getPropertiesOfSurface: invalid argument\n");
+ return -1;
+ }
+
+ *pSurfaceProperties = ivisurf->prop;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerAddSurface(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *addsurf)
+{
+ struct weston_layout *layout = get_instance();
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_surface *next = NULL;
+ int is_surf_in_layer = 0;
+
+ if (ivilayer == NULL || addsurf == NULL) {
+ weston_log("weston_layout_layerAddSurface: invalid argument\n");
+ return -1;
+ }
+
+ is_surf_in_layer = is_surface_in_layer(addsurf, ivilayer);
+ if (is_surf_in_layer == 1) {
+ weston_log("weston_layout_layerAddSurface: addsurf is already available\n");
+ return 0;
+ }
+
+ wl_list_for_each_safe(ivisurf, next, &layout->list_surface, link) {
+ if (ivisurf->id_surface == addsurf->id_surface) {
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ wl_list_insert(&ivilayer->pending.list_surface,
+ &ivisurf->pending.link);
+ break;
+ }
+ }
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_layerRemoveSurface(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *remsurf)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_surface *next = NULL;
+
+ if (ivilayer == NULL || remsurf == NULL) {
+ weston_log("weston_layout_layerRemoveSurface: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(ivisurf, next,
+ &ivilayer->pending.list_surface, pending.link) {
+ if (ivisurf->id_surface == remsurf->id_surface) {
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ break;
+ }
+ }
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_REMOVE;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_surfaceSetSourceRectangle(struct weston_layout_surface *ivisurf,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct weston_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("weston_layout_surfaceSetSourceRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->sourceX = x;
+ prop->sourceY = y;
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+weston_layout_commitChanges(void)
+{
+ struct weston_layout *layout = get_instance();
+
+ commit_list_surface(layout);
+ commit_list_layer(layout);
+ commit_list_screen(layout);
+
+ commit_changes(layout);
+ send_prop(layout);
+ weston_compositor_schedule_repaint(layout->compositor);
+
+ return 0;
+}
diff --git a/ivi-shell/weston-layout.h b/ivi-shell/weston-layout.h
new file mode 100644
index 0000000..2667784
--- /dev/null
+++ b/ivi-shell/weston-layout.h
@@ -0,0 +1,934 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * The weston-layout library supports API set of controlling properties of
+ * surface and layer which groups surfaces. An unique ID whose type is integer
+ * is required to create surface and layer. With the unique ID, surface and
+ * layer are identified to control them. The API set consists of APIs to control
+ * properties of surface and layers about followings,
+ * - visibility.
+ * - opacity.
+ * - clipping (x,y,width,height).
+ * - position and size of it to be displayed.
+ * - orientation per 90 degree.
+ * - add or remove surfaces to a layer.
+ * - order of surfaces/layers in layer/screen to be displayed.
+ * - commit to apply property changes.
+ * - notifications of property change.
+ *
+ * Management of surfaces and layers grouping these surfaces are common way in
+ * In-Vehicle Infotainment system, which integrate several domains in one system.
+ * A layer is allocated to a domain in order to control application surfaces
+ * grouped to the layer all together.
+ */
+
+#ifndef _WESTON_LAYOUT_H_
+#define _WESTON_LAYOUT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "compositor.h"
+
+struct weston_layout_SurfaceProperties
+{
+ float opacity;
+ uint32_t sourceX;
+ uint32_t sourceY;
+ uint32_t sourceWidth;
+ uint32_t sourceHeight;
+ uint32_t origSourceWidth;
+ uint32_t origSourceHeight;
+ int32_t destX;
+ int32_t destY;
+ uint32_t destWidth;
+ uint32_t destHeight;
+ uint32_t orientation;
+ uint32_t visibility;
+ uint32_t frameCounter;
+ uint32_t drawCounter;
+ uint32_t updateCounter;
+ uint32_t pixelformat;
+ uint32_t nativeSurface;
+ uint32_t inputDevicesAcceptance;
+ uint32_t chromaKeyEnabled;
+ uint32_t chromaKeyRed;
+ uint32_t chromaKeyGreen;
+ uint32_t chromaKeyBlue;
+ int32_t creatorPid;
+};
+
+struct weston_layout_LayerProperties
+{
+ float opacity;
+ uint32_t sourceX;
+ uint32_t sourceY;
+ uint32_t sourceWidth;
+ uint32_t sourceHeight;
+ uint32_t origSourceWidth;
+ uint32_t origSourceHeight;
+ int32_t destX;
+ int32_t destY;
+ uint32_t destWidth;
+ uint32_t destHeight;
+ uint32_t orientation;
+ uint32_t visibility;
+ uint32_t type;
+ uint32_t chromaKeyEnabled;
+ uint32_t chromaKeyRed;
+ uint32_t chromaKeyGreen;
+ uint32_t chromaKeyBlue;
+ int32_t creatorPid;
+};
+
+struct weston_layout_layer;
+struct weston_layout_surface;
+struct weston_layout_screen;
+
+typedef struct weston_layout_surface* weston_layout_surface_ptr;
+typedef struct weston_layout_layer* weston_layout_layer_ptr;
+typedef struct weston_layout_screen* weston_layout_screen_ptr;
+
+#define IVI_BIT(x) (1 << (x))
+enum weston_layout_notification_mask {
+ IVI_NOTIFICATION_OPACITY = IVI_BIT(1),
+ IVI_NOTIFICATION_SOURCE_RECT = IVI_BIT(2),
+ IVI_NOTIFICATION_DEST_RECT = IVI_BIT(3),
+ IVI_NOTIFICATION_DIMENSION = IVI_BIT(4),
+ IVI_NOTIFICATION_POSITION = IVI_BIT(5),
+ IVI_NOTIFICATION_ORIENTATION = IVI_BIT(6),
+ IVI_NOTIFICATION_VISIBILITY = IVI_BIT(7),
+ IVI_NOTIFICATION_PIXELFORMAT = IVI_BIT(8),
+ IVI_NOTIFICATION_ADD = IVI_BIT(9),
+ IVI_NOTIFICATION_REMOVE = IVI_BIT(10),
+ IVI_NOTIFICATION_ALL = 0xFFFF
+};
+
+typedef void(*layerPropertyNotificationFunc)(struct weston_layout_layer *ivilayer,
+ struct weston_layout_LayerProperties*,
+ enum weston_layout_notification_mask mask,
+ void *userdata);
+
+typedef void(*surfacePropertyNotificationFunc)(struct weston_layout_surface *ivisurf,
+ struct weston_layout_SurfaceProperties*,
+ enum weston_layout_notification_mask mask,
+ void *userdata);
+
+typedef void(*layerCreateNotificationFunc)(struct weston_layout_layer *ivilayer,
+ void *userdata);
+
+typedef void(*layerRemoveNotificationFunc)(struct weston_layout_layer *ivilayer,
+ void *userdata);
+
+typedef void(*surfaceCreateNotificationFunc)(struct weston_layout_surface *ivisurf,
+ void *userdata);
+
+typedef void(*surfaceRemoveNotificationFunc)(struct weston_layout_surface *ivisurf,
+ void *userdata);
+
+typedef void(*surfaceConfigureNotificationFunc)(struct weston_layout_surface *ivisurf,
+ void *userdata);
+
+/**
+ * \brief to be called by ivi-shell in order to set initail view of
+ * weston_surface.
+ */
+struct weston_view *
+weston_layout_get_weston_view(struct weston_layout_surface *surface);
+
+/**
+ * \brief initialize weston-layout
+ */
+void
+weston_layout_initWithCompositor(struct weston_compositor *ec);
+
+/**
+ * \brief register for notification when layer is created
+ */
+int32_t
+weston_layout_setNotificationCreateLayer(layerCreateNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when layer is removed
+ */
+int32_t
+weston_layout_setNotificationRemoveLayer(layerRemoveNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is created
+ */
+int32_t
+weston_layout_setNotificationCreateSurface(surfaceCreateNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is removed
+ */
+int32_t
+weston_layout_setNotificationRemoveSurface(surfaceRemoveNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is configured
+ */
+int32_t
+weston_layout_setNotificationConfigureSurface(surfaceConfigureNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief get id of surface from weston_layout_surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+uint32_t
+weston_layout_getIdOfSurface(struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief get id of layer from weston_layout_layer
+ *
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+uint32_t
+weston_layout_getIdOfLayer(struct weston_layout_layer *ivilayer);
+
+/**
+ * \brief get weston_layout_layer from id of layer
+ *
+ * \return (struct weston_layout_layer *)
+ * if the method call was successful
+ * \return NULL if the client can not call the method on the service.
+ */
+struct weston_layout_layer *
+weston_layout_getLayerFromId(uint32_t id_layer);
+
+/**
+ * \brief get weston_layout_surface from id of surface
+ *
+ * \return (struct weston_layout_surface *)
+ * if the method call was successful
+ * \return NULL if the client can not call the method on the service.
+ */
+struct weston_layout_surface *
+weston_layout_getSurfaceFromId(uint32_t id_surface);
+
+/**
+ * \brief get weston_layout_screen from id of screen
+ *
+ * \return (struct weston_layout_screen *)
+ * if the method call was successful
+ * \return NULL if the client can not call the method on the service.
+ */
+struct weston_layout_screen *
+weston_layout_getScreenFromId(uint32_t id_screen);
+
+/**
+ * \brief Get the screen resolution of a specific screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getScreenResolution(struct weston_layout_screen *iviscrn,
+ uint32_t *pWidth,
+ uint32_t *pHeight);
+
+/**
+ * \brief register for notification on property changes of surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceAddNotification(struct weston_layout_surface *ivisurf,
+ surfacePropertyNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief remove notification on property changes of surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceRemoveNotification(struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief Create a surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+struct weston_layout_surface *
+weston_layout_surfaceCreate(struct weston_surface *wl_surface,
+ uint32_t id_surface);
+
+/**
+ * \brief Set the native content of an application to be used as surface content.
+ * If wl_surface is NULL, remove the native content of a surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetNativeContent(struct weston_surface *wl_surface,
+ uint32_t width,
+ uint32_t height,
+ uint32_t id_surface);
+
+/**
+ * \brief initialize weston_layout_surface dest/source width and height
+ */
+void
+weston_layout_surfaceConfigure(struct weston_layout_surface *ivisurf,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Remove a surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceRemove(struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief Set from which kind of devices the surface can accept input events.
+ * By default, a surface accept input events from all kind of devices (keyboards, pointer, ...)
+ * By calling this function, you can adjust surface preferences. Note that this function only
+ * adjust the acceptance for the specified devices. Non specified are keept untouched.
+ *
+ * Typicall use case for this function is when dealing with pointer or touch events.
+ * Those are normally dispatched to the first visible surface below the coordinate.
+ * If you want a different behavior (i.e. forward events to an other surface below the coordinate,
+ * you can set all above surfaces to refuse input events)
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_UpdateInputEventAcceptanceOn(struct weston_layout_surface *ivisurf,
+ uint32_t devices,
+ uint32_t acceptance);
+
+/**
+ * \brief Get the layer properties
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getPropertiesOfLayer(struct weston_layout_layer *ivilayer,
+ struct weston_layout_LayerProperties *pLayerProperties);
+
+/**
+ * \brief Get the number of hardware layers of a screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getNumberOfHardwareLayers(uint32_t id_screen,
+ uint32_t *pNumberOfHardwareLayers);
+
+/**
+ * \brief Get the screens
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getScreens(uint32_t *pLength, weston_layout_screen_ptr **ppArray);
+
+/**
+ * \brief Get the screens under the given layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getScreensUnderLayer(struct weston_layout_layer *ivilayer,
+ uint32_t *pLength,
+ weston_layout_screen_ptr **ppArray);
+
+/**
+ * \brief Get all Layers which are currently registered and managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getLayers(uint32_t *pLength, weston_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Layers of the given screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getLayersOnScreen(struct weston_layout_screen *iviscrn,
+ uint32_t *pLength,
+ weston_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Layers under the given surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getLayersUnderSurface(struct weston_layout_surface *ivisurf,
+ uint32_t *pLength,
+ weston_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Surfaces which are currently registered and managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getSurfaces(uint32_t *pLength, weston_layout_surface_ptr **ppArray);
+
+/**
+ * \brief Get all Surfaces which are currently registered to a given layer and are managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getSurfacesOnLayer(struct weston_layout_layer *ivilayer,
+ uint32_t *pLength,
+ weston_layout_surface_ptr **ppArray);
+
+/**
+ * \brief Create a layer which should be managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+struct weston_layout_layer *
+weston_layout_layerCreateWithDimension(uint32_t id_layer,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Removes a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerRemove(struct weston_layout_layer *ivilayer);
+
+/**
+ * \brief Get the current type of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetType(struct weston_layout_layer *ivilayer,
+ uint32_t *pLayerType);
+
+/**
+ * \brief Set the visibility of a layer. If a layer is not visible, the layer and its
+ * surfaces will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetVisibility(struct weston_layout_layer *ivilayer,
+ uint32_t newVisibility);
+
+/**
+ * \brief Get the visibility of a layer. If a layer is not visible, the layer and its
+ * surfaces will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetVisibility(struct weston_layout_layer *ivilayer,
+ uint32_t *pVisibility);
+
+/**
+ * \brief Set the opacity of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetOpacity(struct weston_layout_layer *ivilayer, float opacity);
+
+/**
+ * \brief Get the opacity of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetOpacity(struct weston_layout_layer *ivilayer, float *pOpacity);
+
+/**
+ * \brief Set the area of a layer which should be used for the rendering.
+ * Only this part will be visible.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetSourceRectangle(struct weston_layout_layer *ivilayer,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Set the destination area on the display for a layer.
+ * The layer will be scaled and positioned to this rectangle for rendering
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetDestinationRectangle(struct weston_layout_layer *ivilayer,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Get the horizontal and vertical dimension of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetDimension(struct weston_layout_layer *ivilayer,
+ uint32_t *pDimension);
+
+/**
+ * \brief Set the horizontal and vertical dimension of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetDimension(struct weston_layout_layer *ivilayer,
+ uint32_t *pDimension);
+
+/**
+ * \brief Get the horizontal and vertical position of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetPosition(struct weston_layout_layer *ivilayer,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the horizontal and vertical position of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetPosition(struct weston_layout_layer *ivilayer,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the orientation of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetOrientation(struct weston_layout_layer *ivilayer,
+ uint32_t orientation);
+
+/**
+ * \brief Gets the orientation of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetOrientation(struct weston_layout_layer *ivilayer,
+ uint32_t *pOrientation);
+
+/**
+ * \brief Sets the color value which defines the transparency value.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetChromaKey(struct weston_layout_layer *ivilayer,
+ uint32_t* pColor);
+
+/**
+ * \brief Sets render order of surfaces within one layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerSetRenderOrder(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface **pSurface,
+ uint32_t number);
+
+/**
+ * \brief Get the capabilities of a layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerGetCapabilities(struct weston_layout_layer *ivilayer,
+ uint32_t *pCapabilities);
+
+/**
+ * \brief Get the possible capabilities of a layertype
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerTypeGetCapabilities(uint32_t layerType,
+ uint32_t *pCapabilities);
+
+/**
+ * \brief Create the logical surface, which has no native buffer associated
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceInitialize(struct weston_layout_surface **pSurface);
+
+/**
+ * \brief Set the visibility of a surface.
+ * If a surface is not visible it will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetVisibility(struct weston_layout_surface *ivisurf,
+ uint32_t newVisibility);
+
+/**
+ * \brief Get the visibility of a surface.
+ * If a surface is not visible it will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetVisibility(struct weston_layout_surface *ivisurf,
+ uint32_t *pVisibility);
+
+/**
+ * \brief Set the opacity of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetOpacity(struct weston_layout_surface *ivisurf,
+ float opacity);
+
+/**
+ * \brief Get the opacity of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetOpacity(struct weston_layout_surface *ivisurf,
+ float *pOpacity);
+
+/**
+ * \brief Set the keyboard focus on a certain surface
+ * To receive keyboard events, 2 conditions must be fulfilled:
+ * 1- The surface must accept events from keyboard. See ilm_UpdateInputEventAcceptanceOn
+ * 2- The keyboard focus must be set on that surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_SetKeyboardFocusOn(struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief Get the indentifier of the surface which hold the keyboard focus
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_GetKeyboardFocusSurfaceId(struct weston_layout_surface **pSurfaceId);
+
+/**
+ * \brief Set the destination area of a surface within a layer for rendering.
+ * The surface will be scaled to this rectangle for rendering.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetDestinationRectangle(struct weston_layout_surface *ivisurf,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Set the horizontal and vertical dimension of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetDimension(struct weston_layout_surface *ivisurf,
+ uint32_t *pDimension);
+
+/**
+ * \brief Get the horizontal and vertical dimension of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetDimension(struct weston_layout_surface *ivisurf,
+ uint32_t *pDimension);
+
+/**
+ * \brief Sets the horizontal and vertical position of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetPosition(struct weston_layout_surface *ivisurf,
+ int32_t *pPosition);
+
+/**
+ * \brief Get the horizontal and vertical position of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetPosition(struct weston_layout_surface *ivisurf,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the orientation of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetOrientation(struct weston_layout_surface *ivisurf,
+ uint32_t orientation);
+
+/**
+ * \brief Gets the orientation of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetOrientation(struct weston_layout_surface *ivisurf,
+ uint32_t *pOrientation);
+
+/**
+ * \brief Gets the pixelformat of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceGetPixelformat(struct weston_layout_layer *ivisurf,
+ uint32_t *pPixelformat);
+
+/**
+ * \brief Sets the color value which defines the transparency value of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetChromaKey(struct weston_layout_surface *ivisurf,
+ uint32_t* pColor);
+
+/**
+ * \brief Add a layer to a screen which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_screenAddLayer(struct weston_layout_screen *iviscrn,
+ struct weston_layout_layer *addlayer);
+
+/**
+ * \brief Sets render order of layers on a display
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_screenSetRenderOrder(struct weston_layout_screen *iviscrn,
+ struct weston_layout_layer **pLayer,
+ const uint32_t number);
+
+/**
+ * \brief Take a screenshot from the current displayed layer scene.
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_takeScreenshot(struct weston_layout_screen *iviscrn,
+ const char *filename);
+
+/**
+ * \brief Take a screenshot of a certain layer
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_takeLayerScreenshot(const char *filename,
+ struct weston_layout_layer *ivilayer);
+
+/**
+ * \brief Take a screenshot of a certain surface
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_takeSurfaceScreenshot(const char *filename,
+ struct weston_layout_surface *ivisurf);
+
+/**
+ * \brief Enable or disable a rendering optimization
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_SetOptimizationMode(uint32_t id, uint32_t mode);
+
+/**
+ * \brief Get the current enablement for an optimization
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_GetOptimizationMode(uint32_t id, uint32_t *pMode);
+
+/**
+ * \brief register for notification on property changes of layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerAddNotification(struct weston_layout_layer *ivilayer,
+ layerPropertyNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief remove notification on property changes of layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerRemoveNotification(struct weston_layout_layer *ivilayer);
+
+/**
+ * \brief Get the surface properties
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_getPropertiesOfSurface(struct weston_layout_surface *ivisurf,
+ struct weston_layout_SurfaceProperties *pSurfaceProperties);
+
+/**
+ * \brief Add a surface to a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerAddSurface(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *addsurf);
+
+/**
+ * \brief Removes a surface from a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_layerRemoveSurface(struct weston_layout_layer *ivilayer,
+ struct weston_layout_surface *remsurf);
+
+/**
+ * \brief Set the area of a surface which should be used for the rendering.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_surfaceSetSourceRectangle(struct weston_layout_surface *ivisurf,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Commit all changes and execute all enqueued commands since last commit.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the client can not call the method on the service.
+ */
+int32_t
+weston_layout_commitChanges(void);
+
+#ifdef __cplusplus
+} /**/
+#endif /* __cplusplus */
+
+#endif /* _WESTON_LAYOUT_H_ */
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 09:59:48 UTC
Permalink
building ivi-shell.so and libweston-layout.so.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
Makefile.am | 1 +
configure.ac | 15 ++++++++++++++-
ivi-shell/Makefile.am | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+), 1 deletion(-)
create mode 100644 ivi-shell/Makefile.am

diff --git a/Makefile.am b/Makefile.am
index f22c542..1bc35e2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,6 +11,7 @@ SUBDIRS = \
src \
$(xwayland_subdir) \
desktop-shell \
+ ivi-shell \
clients \
data \
protocol \
diff --git a/configure.ac b/configure.ac
index cce1850..4c0a90f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -409,6 +409,16 @@ if test "x$enable_dbus" != "xno"; then
fi
AM_CONDITIONAL(ENABLE_DBUS, test "x$enable_dbus" = "xyes")

+# ivi-shell support
+AC_ARG_ENABLE(ivi-shell,
+ AS_HELP_STRING([--disable-ivi-shell],
+ [do not build ivi-shell server plugin and client]),,
+ enable_ivi_shell=yes)
+AM_CONDITIONAL(ENABLE_IVI_SHELL, test "x$enable_ivi_shell" = "xyes")
+if test x$enable_ivi_shell = xyes; then
+ PKG_CHECK_MODULES(IVI_SHELL, [cairo])
+fi
+
AC_ARG_ENABLE(wcap-tools, [ --disable-wcap-tools],, enable_wcap_tools=yes)
AM_CONDITIONAL(BUILD_WCAP_TOOLS, test x$enable_wcap_tools = xyes)
if test x$enable_wcap_tools = xyes; then
@@ -505,7 +515,8 @@ AC_CONFIG_FILES([Makefile
data/Makefile
protocol/Makefile
man/Makefile
- tests/Makefile])
+ tests/Makefile
+ ivi-shell/Makefile])
AC_OUTPUT

AC_MSG_RESULT([
@@ -519,6 +530,8 @@ AC_MSG_RESULT([
XWayland ${enable_xwayland}
dbus ${enable_dbus}

+ ivi-shell ${enable_ivi_shell}
+
Build wcap utility ${enable_wcap_tools}

weston-launch utility ${enable_weston_launch}
diff --git a/ivi-shell/Makefile.am b/ivi-shell/Makefile.am
new file mode 100644
index 0000000..d0c0d62
--- /dev/null
+++ b/ivi-shell/Makefile.am
@@ -0,0 +1,52 @@
+moduledir = $(libdir)/weston
+
+module_LTLIBRARIES = \
+ $(libweston_layout) \
+ $(ivi_shell)
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/shared \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src \
+ -DDATADIR='"$(datadir)"' \
+ -DMODULEDIR='"$(moduledir)"' \
+ -DLIBEXECDIR='"$(libexecdir)"' \
+ -DIN_WESTON
+
+westonincludedir = $(includedir)/weston
+westoninclude_HEADERS =
+
+if ENABLE_IVI_SHELL
+westoninclude_HEADERS += \
+ ivi-application-client-protocol.h \
+ weston-layout.h
+
+libweston_layout = libweston-layout.la
+libweston_layout_la_LDFLAGS = -avoid-version
+libweston_layout_la_LIBADD = $(IVI_SHELL_LIBS) ../shared/libshared.la
+libweston_layout_la_CFLAGS = $(GCC_CFLAGS) $(IVI_SHELL_CFLAGS)
+libweston_layout_la_SOURCES = \
+ weston-layout.c \
+ weston-layout.h
+
+ivi_shell = ivi-shell.la
+ivi_shell_la_LDFLAGS = -module -avoid-version
+ivi_shell_la_LIBADD = $(COMPOSITOR_LIBS) $(IVI_SHELL_LIBS) ./libweston-layout.la
+ivi_shell_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) $(IVI_SHELL_CFLAGS)
+ivi_shell_la_SOURCES = \
+ ivi-shell.c \
+ weston-layout.h \
+ ivi-application-protocol.c \
+ ivi-application-server-protocol.h
+
+endif
+
+BUILT_SOURCES = \
+ ivi-application-protocol.c \
+ ivi-application-server-protocol.h \
+ ivi-application-client-protocol.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
+wayland_protocoldir = $(top_srcdir)/protocol
+include $(top_srcdir)/wayland-scanner.mk
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:00:43 UTC
Permalink
The reference protocol is used between hmi-controller and
hmi-controller-homescreen.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
protocol/ivi-hmi-controller.xml | 105 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
create mode 100644 protocol/ivi-hmi-controller.xml

diff --git a/protocol/ivi-hmi-controller.xml b/protocol/ivi-hmi-controller.xml
new file mode 100644
index 0000000..04e22f4
--- /dev/null
+++ b/protocol/ivi-hmi-controller.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ivi_hmi_controller">
+
+ <copyright>
+ Copyright (C) 2013 DENSO CORPORATION
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ </copyright>
+
+ <interface name="ivi_hmi_controller" version="1">
+ <description summary="set up and control IVI style UI">
+ Currently it's possible to set up surface for background, panel,
+ buttons, and workspace.
+ </description>
+
+ <request name="set_background">
+ <description summary="set surface drawing background by surface ID"/>
+ <arg name="srf_id" type="uint"/>
+ </request>
+
+ <request name="set_panel">
+ <description summary="set surface drawing panel by surface ID"/>
+ <arg name="srf_id" type="uint"/>
+ </request>
+
+ <request name="set_button">
+ <description summary="set surface drawing button by surface ID">
+ Several buttons are regitered on panel by using arg; number.
+ </description>
+ <arg name="srf_id" type="uint"/>
+ <arg name="number" type="uint"/>
+ </request>
+
+ <request name="set_home_button">
+ <description summary="set surface drawing home button by surface ID"/>
+ <arg name="srf_id" type="uint"/>
+ </request>
+
+ <request name="set_workspacebackground">
+ <description summary="set surface drawing background of workspace by surface ID"/>
+ <arg name="srf_id" type="uint"/>
+ </request>
+
+ <request name="add_launchers">
+ <description summary="set a list of surface drawing launchers by a list of surface ID">
+ Per calling this request, a group of launchers are added.
+ </description>
+ <arg name="srf_ids" type="array"/>
+ <arg name="icon_size" type="uint"/>
+ </request>
+
+ <request name="workspace_control">
+ <description summary="start controlling workspace by server">
+ Give seat to the server to be controlled by server side.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ <arg name="serial" type="uint"/>
+ </request>
+
+ <enum name="layout_mode">
+ <entry name="tiling" value="0"/>
+ <entry name="side_by_side" value="1"/>
+ <entry name="full_screen" value="2"/>
+ <entry name="random" value="3" />
+ </enum>
+
+ <request name="switch_mode">
+ <description summary="request mode switch of application layout"/>
+ <arg name="layout_mode" type="uint"/>
+ </request>
+
+ <enum name="home">
+ <entry name="off" value="0"/>
+ <entry name="on" value="1"/>
+ </enum>
+
+ <request name="home">
+ <description summary="request showing workspace or disable"/>
+ <arg name="home" type="uint"/>
+ </request>
+
+ <event name="workspace_end_control">
+ <description summary="notify controlling workspace end"/>
+ <arg name="is_controlled" type="int"/>
+ </event>
+
+ </interface>
+
+</protocol>
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:01:31 UTC
Permalink
From: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at denso.co.jp>

---
protocol/Makefile.am | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/protocol/Makefile.am b/protocol/Makefile.am
index 9913f16..140aef5 100644
--- a/protocol/Makefile.am
+++ b/protocol/Makefile.am
@@ -9,7 +9,8 @@ protocol_sources = \
wayland-test.xml \
xdg-shell.xml \
scaler.xml \
- ivi-application.xml
+ ivi-application.xml \
+ ivi-hmi-controller.xml

if HAVE_XMLLINT
.PHONY: validate
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:02:20 UTC
Permalink
The library is used to manage layout of surfaces/layers. Layout change is
triggered by ivi-hmi-controller protocol, ivi-hmi-controller.xml. A reference
how to use the protocol, see hmi-controller-homescreen.

In-Vehicle Infotainment system usually manage properties of surfaces/layers
by only a central component which decide where surfaces/layers shall be. This
reference show examples to implement the central component as a module of
weston.

Default Scene graph of UI is defined in hmi_controller_create. It consists of
- In the bottom, a base layer to group surfaces of background, panel,
and buttons
- Next, a application layer to show application surfaces.
- Workspace background layer to show a surface of background image.
- Workspace layer to show launcher to launch application with icons. Paths to
binary and icon are defined in weston.ini. The width of this layer is longer
than the size of screen because a workspace has several pages and is
controlled by motion of input.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
ivi-shell/hmi-controller.c | 1776 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1776 insertions(+)
create mode 100644 ivi-shell/hmi-controller.c

diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
new file mode 100644
index 0000000..3cfb19b
--- /dev/null
+++ b/ivi-shell/hmi-controller.c
@@ -0,0 +1,1776 @@
+/*
+ * Copyright (C) 2014 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * A reference implementation how to use weston-layout APIs in order to manage
+ * layout of surfaces/layers. Layout change is triggered by ivi-hmi-controller
+ * protocol, ivi-hmi-controller.xml. A reference how to use the protocol, see
+ * hmi-controller-homescreen.
+ *
+ * In-Vehicle Infotainment system usually manage properties of surfaces/layers
+ * by only a central component which decide where surfaces/layers shall be. This
+ * reference show examples to implement the central component as a module of weston.
+ *
+ * Default Scene graph of UI is defined in hmi_controller_create. It consists of
+ * - In the bottom, a base layer to group surfaces of background, panel,
+ * and buttons
+ * - Next, a application layer to show application surfaces.
+ * - Workspace background layer to show a surface of background image.
+ * - Workspace layer to show launcher to launch application with icons. Paths to
+ * binary and icon are defined in weston.ini. The width of this layer is longer
+ * than the size of screen because a workspace has several pages and is controlled
+ * by motion of input.
+ *
+ * TODO: animation method shall be refined
+ * TODO: support fade-in when UI is ready
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+#include <assert.h>
+#include <time.h>
+
+#include "weston-layout.h"
+#include "hmi-controller-homescreen.h"
+#include "ivi-hmi-controller-server-protocol.h"
+
+/*****************************************************************************
+ * structure, globals
+ ****************************************************************************/
+struct hmi_controller_layer {
+ struct weston_layout_layer *ivilayer;
+ uint32_t id_layer;
+ int32_t x;
+ int32_t y;
+ uint32_t width;
+ uint32_t height;
+};
+
+struct link_layer {
+ struct weston_layout_layer *layout_layer;
+ struct wl_list link;
+};
+
+struct link_animation {
+ struct hmi_controller_animation *animation;
+ struct wl_list link;
+};
+
+struct hmi_controller_animation;
+typedef void (*hmi_controller_animation_frame_func)(void *animation, uint32_t timestamp);
+typedef void (*hmi_controller_animation_frame_user_func)(void *animation);
+typedef void (*hmi_controller_animation_destroy_func)(struct hmi_controller_animation *animation);
+
+struct move_animation_user_data {
+ struct weston_layout_layer* layer;
+ struct animation_set *anima_set;
+ struct hmi_controller *hmi_ctrl;
+};
+
+struct hmi_controller_animation {
+ void *user_data;
+ uint32_t time_start;
+ uint32_t is_done;
+ hmi_controller_animation_frame_func frame_func;
+ hmi_controller_animation_frame_user_func frame_user_func;
+ hmi_controller_animation_destroy_func destroy_func;
+};
+
+struct hmi_controller_animation_fade {
+ struct hmi_controller_animation base;
+ double start;
+ double end;
+ struct weston_spring spring;
+};
+
+struct hmi_controller_animation_move {
+ struct hmi_controller_animation base;
+ double pos;
+ double pos_start;
+ double pos_end;
+ double v0;
+ double a;
+ double time_end;
+};
+
+struct hmi_controller_fade {
+ uint32_t isFadeIn;
+ struct hmi_controller_animation_fade *animation;
+ struct animation_set *anima_set;
+ struct wl_list layer_list;
+};
+
+struct animation_set {
+ struct wl_event_source *event_source;
+ struct wl_list animation_list;
+};
+
+struct
+hmi_server_setting {
+ uint32_t base_layer_id;
+ uint32_t application_layer_id;
+ uint32_t workspace_background_layer_id;
+ uint32_t workspace_layer_id;
+ uint32_t panel_height;
+};
+
+struct hmi_controller
+{
+ struct hmi_server_setting *hmi_setting;
+ struct hmi_controller_layer base_layer;
+ struct hmi_controller_layer application_layer;
+ struct hmi_controller_layer workspace_background_layer;
+ struct hmi_controller_layer workspace_layer;
+ enum ivi_hmi_controller_layout_mode layout_mode;
+
+ struct animation_set *anima_set;
+ struct hmi_controller_fade workspace_fade;
+ struct hmi_controller_animation_move *workspace_swipe_animation;
+ int32_t workspace_count;
+ struct wl_array ui_widgets;
+ int32_t is_initialized;
+};
+
+/*****************************************************************************
+ * local functions
+ ****************************************************************************/
+static void *
+fail_on_null(void *p, size_t size, char* file, int32_t line)
+{
+ if (size && !p) {
+ fprintf(stderr, "%s(%d) %zd: out of memory\n", file, line, size);
+ exit(EXIT_FAILURE);
+ }
+
+ return p;
+}
+
+static void *
+mem_alloc(size_t size, char* file, int32_t line)
+{
+ return fail_on_null(calloc(1, size), size, file, line);
+}
+
+#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
+
+static int32_t
+is_surf_in_uiWidget(struct hmi_controller *hmi_ctrl,
+ struct weston_layout_surface *ivisurf)
+{
+ uint32_t id = weston_layout_getIdOfSurface(ivisurf);
+
+ uint32_t *ui_widget_id = NULL;
+ wl_array_for_each (ui_widget_id, &hmi_ctrl->ui_widgets) {
+ if (*ui_widget_id == id) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Internal methods called by mainly ivi_hmi_controller_switch_mode
+ * This reference shows 4 examples how to use weston_layout APIs.
+ */
+static void
+mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
+ weston_layout_surface_ptr *ppSurface,
+ uint32_t surface_length,
+ struct hmi_controller_layer *layer)
+{
+ const float surface_width = (float)layer->width * 0.25;
+ const float surface_height = (float)layer->height * 0.5;
+ int32_t surface_x = 0;
+ int32_t surface_y = 0;
+ struct weston_layout_surface *ivisurf = NULL;
+ int32_t ret = 0;
+
+ uint32_t i = 0;
+ uint32_t num = 1;
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ if (num <= 8) {
+ if (num < 5) {
+ surface_x = (int32_t)((num - 1) * (surface_width));
+ surface_y = 0;
+ }
+ else {
+ surface_x = (int32_t)((num - 5) * (surface_width));
+ surface_y = (int32_t)surface_height;
+ }
+ ret = weston_layout_surfaceSetDestinationRectangle(ivisurf, surface_x, surface_y,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ num++;
+ continue;
+ }
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 0);
+ assert(!ret);
+ }
+}
+
+static void
+mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
+ weston_layout_surface_ptr *ppSurface,
+ uint32_t surface_length,
+ struct hmi_controller_layer *layer)
+{
+ uint32_t surface_width = layer->width / 2;
+ uint32_t surface_height = layer->height;
+ struct weston_layout_surface *ivisurf = NULL;
+ int32_t ret = 0;
+
+ uint32_t i = 0;
+ uint32_t num = 1;
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ if (num == 1) {
+ ret = weston_layout_surfaceSetDestinationRectangle(ivisurf, 0, 0,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ num++;
+ continue;
+ }
+ else if (num == 2) {
+ ret = weston_layout_surfaceSetDestinationRectangle(ivisurf, surface_width, 0,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ num++;
+ continue;
+ }
+
+ weston_layout_surfaceSetVisibility(ivisurf, 0);
+ assert(!ret);
+ }
+}
+
+static void
+mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
+ weston_layout_surface_ptr *ppSurface, uint32_t surface_length,
+ struct hmi_controller_layer *layer)
+{
+ const uint32_t surface_width = layer->width;
+ const uint32_t surface_height = layer->height;
+ struct weston_layout_surface *ivisurf = NULL;
+ int32_t ret = 0;
+
+ uint32_t i = 0;
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ ret = weston_layout_surfaceSetDestinationRectangle(ivisurf, 0, 0,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+ }
+}
+
+static void
+mode_random_replace(struct hmi_controller *hmi_ctrl,
+ weston_layout_surface_ptr *ppSurface, uint32_t surface_length,
+ struct hmi_controller_layer *layer)
+{
+ const uint32_t surface_width = (uint32_t)(layer->width * 0.25f);
+ const uint32_t surface_height = (uint32_t)(layer->height * 0.25f);
+ uint32_t surface_x = 0;
+ uint32_t surface_y = 0;
+ struct weston_layout_surface *ivisurf = NULL;
+ int32_t ret = 0;
+
+ uint32_t i = 0;
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ surface_x = rand() % (layer->width - surface_width);
+ surface_y = rand() % (layer->height - surface_height);
+
+ ret = weston_layout_surfaceSetDestinationRectangle(ivisurf, surface_x, surface_y,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+ }
+}
+
+static int32_t
+has_applicatipn_surface(struct hmi_controller *hmi_ctrl, weston_layout_surface_ptr *ppSurface,
+ uint32_t surface_length)
+{
+ struct weston_layout_surface *ivisurf = NULL;
+ uint32_t i = 0;
+
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Supports 4 example to layout of application surfaces;
+ * tiling, side by side, fullscreen, and random.
+ */
+static void
+switch_mode(struct hmi_controller *hmi_ctrl,
+ enum ivi_hmi_controller_layout_mode layout_mode)
+{
+ if (!hmi_ctrl->is_initialized) {
+ return;
+ }
+
+ struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
+ weston_layout_surface_ptr *ppSurface = NULL;
+ uint32_t surface_length = 0;
+ int32_t ret = 0;
+
+ hmi_ctrl->layout_mode = layout_mode;
+
+ ret = weston_layout_getSurfaces(&surface_length, &ppSurface);
+ assert(!ret);
+
+ if (!has_applicatipn_surface(hmi_ctrl, ppSurface, surface_length)) {
+ free(ppSurface);
+ ppSurface = NULL;
+ return;
+ }
+
+ switch (layout_mode) {
+ case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
+ mode_divided_into_tiling(hmi_ctrl, ppSurface, surface_length, layer);
+ break;
+ case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
+ mode_divided_into_sidebyside(hmi_ctrl, ppSurface, surface_length, layer);
+ break;
+ case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
+ mode_fullscreen_someone(hmi_ctrl, ppSurface, surface_length, layer);
+ break;
+ case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
+ mode_random_replace(hmi_ctrl, ppSurface, surface_length, layer);
+ break;
+ }
+
+ weston_layout_commitChanges();
+
+ free(ppSurface);
+ ppSurface = NULL;
+
+ return;
+}
+
+/**
+ * Internal method for animation
+ */
+static void
+hmi_controller_animation_frame(
+ struct hmi_controller_animation *animation, uint32_t timestamp)
+{
+ if (0 == animation->time_start) {
+ animation->time_start = timestamp;
+ }
+
+ animation->frame_func(animation, timestamp);
+ animation->frame_user_func(animation);
+}
+
+static int
+animation_set_do_anima(void* data)
+{
+ struct animation_set *anima_set = data;
+ uint32_t fps = 30;
+
+ if (wl_list_empty(&anima_set->animation_list)) {
+ wl_event_source_timer_update(anima_set->event_source, 0);
+ return 1;
+ }
+
+ wl_event_source_timer_update(anima_set->event_source, 1000 / fps);
+
+ struct timespec timestamp = {0};
+ clock_gettime(CLOCK_MONOTONIC, &timestamp);
+ uint32_t msec = (1e+3 * timestamp.tv_sec + 1e-6 * timestamp.tv_nsec);
+
+ struct link_animation *link_animation = NULL;
+ struct link_animation *next = NULL;
+
+ wl_list_for_each_safe(link_animation, next, &anima_set->animation_list, link) {
+ hmi_controller_animation_frame(link_animation->animation, msec);
+ }
+
+ weston_layout_commitChanges();
+ return 1;
+}
+
+static struct animation_set *
+animation_set_create(struct weston_compositor* ec)
+{
+ struct animation_set *anima_set = MEM_ALLOC(sizeof(*anima_set));
+
+ wl_list_init(&anima_set->animation_list);
+
+ struct wl_event_loop *loop = wl_display_get_event_loop(ec->wl_display);
+ anima_set->event_source = wl_event_loop_add_timer(loop, animation_set_do_anima, anima_set);
+ wl_event_source_timer_update(anima_set->event_source, 0);
+
+ return anima_set;
+}
+
+static void
+animation_set_add_animation(struct animation_set *anima_set,
+ struct hmi_controller_animation *anima)
+{
+ struct link_animation *link_anima = NULL;
+
+ link_anima = MEM_ALLOC(sizeof(*link_anima));
+ if (NULL == link_anima) {
+ return;
+ }
+
+ link_anima->animation = anima;
+ wl_list_insert(&anima_set->animation_list, &link_anima->link);
+ wl_event_source_timer_update(anima_set->event_source, 1);
+}
+
+static void
+animation_set_remove_animation(struct animation_set *anima_set,
+ struct hmi_controller_animation *anima)
+{
+ struct link_animation *link_animation = NULL;
+ struct link_animation *next = NULL;
+
+ wl_list_for_each_safe(link_animation, next, &anima_set->animation_list, link) {
+ if (link_animation->animation == anima) {
+ wl_list_remove(&link_animation->link);
+ free(link_animation);
+ break;
+ }
+ }
+}
+
+static void
+hmi_controller_animation_spring_frame(
+ struct hmi_controller_animation_fade *animation, uint32_t timestamp)
+{
+ if (0 == animation->spring.timestamp) {
+ animation->spring.timestamp = timestamp;
+ }
+
+ weston_spring_update(&animation->spring, timestamp);
+ animation->base.is_done = weston_spring_done(&animation->spring);
+}
+
+static void
+hmi_controller_animation_move_frame(
+ struct hmi_controller_animation_move *animation, uint32_t timestamp)
+{
+ double s = animation->pos_start;
+ double t = timestamp - animation->base.time_start;
+ double v0 = animation->v0;
+ double a = animation->a;
+ double time_end = animation->time_end;
+
+ if (time_end <= t) {
+ animation->pos = animation->pos_end;
+ animation->base.is_done = 1;
+ } else {
+ animation->pos = v0 * t + 0.5 * a * t * t + s;
+ }
+}
+
+static void
+hmi_controller_animation_destroy(struct hmi_controller_animation *animation)
+{
+ if (animation->destroy_func) {
+ animation->destroy_func(animation);
+ }
+
+ free(animation);
+}
+
+static void
+hmi_controller_fade_animation_destroy(struct hmi_controller_animation *animation)
+{
+ struct hmi_controller_fade *fade = animation->user_data;
+ animation_set_remove_animation(fade->anima_set, animation);
+ fade->animation = NULL;
+ animation->user_data = NULL;
+}
+
+static struct hmi_controller_animation_fade *
+hmi_controller_animation_fade_create(double start, double end, double k,
+ hmi_controller_animation_frame_user_func frame_user_func, void* user_data,
+ hmi_controller_animation_destroy_func destroy_func)
+{
+ struct hmi_controller_animation_fade* animation = MEM_ALLOC(sizeof(*animation));
+
+ animation->base.frame_user_func = frame_user_func;
+ animation->base.user_data = user_data;
+ animation->base.frame_func =
+ (hmi_controller_animation_frame_func)hmi_controller_animation_spring_frame;
+ animation->base.destroy_func = destroy_func;
+
+ animation->start = start;
+ animation->end = end;
+ weston_spring_init(&animation->spring, k, start, end);
+ animation->spring.friction = 1400;
+ animation->spring.previous = -(end - start) * 0.03;
+
+ return animation;
+}
+
+static struct hmi_controller_animation_move *
+hmi_controller_animation_move_create(
+ double pos_start, double pos_end, double v_start, double v_end,
+ hmi_controller_animation_frame_user_func frame_user_func, void* user_data,
+ hmi_controller_animation_destroy_func destroy_func)
+{
+ struct hmi_controller_animation_move* animation = MEM_ALLOC(sizeof(*animation));
+
+ animation->base.frame_user_func = frame_user_func;
+ animation->base.user_data = user_data;
+ animation->base.frame_func =
+ (hmi_controller_animation_frame_func)hmi_controller_animation_move_frame;
+ animation->base.destroy_func = destroy_func;
+
+ animation->pos_start = pos_start;
+ animation->pos_end = pos_end;
+ animation->v0 = v_start;
+ animation->pos = pos_start;
+
+ double dx = (pos_end - pos_start);
+
+ if (1e-3 < fabs(dx)) {
+ animation->a = 0.5 * (v_end * v_end - v_start * v_start) / dx;
+ if (1e-6 < fabs(animation->a)) {
+ animation->time_end = (v_end - v_start) / animation->a;
+
+ } else {
+ animation->a = 0;
+ animation->time_end = fabs(dx / animation->v0);
+ }
+
+ } else {
+ animation->time_end = 0;
+ }
+
+ return animation;
+}
+
+static double
+hmi_controller_animation_fade_alpha_get(struct hmi_controller_animation_fade* animation)
+{
+ if (animation->spring.current > 0.999) {
+ return 1.0;
+ } else if (animation->spring.current < 0.001 ) {
+ return 0.0;
+ } else {
+ return animation->spring.current;
+ }
+}
+
+static uint32_t
+hmi_controller_animation_is_done(struct hmi_controller_animation *animation)
+{
+ return animation->is_done;
+}
+
+static void
+hmi_controller_fade_update(struct hmi_controller_animation_fade *animation, double end)
+{
+ animation->spring.target = end;
+}
+
+static void
+hmi_controller_anima_fade_user_frame(struct hmi_controller_animation_fade *animation)
+{
+ double alpha = hmi_controller_animation_fade_alpha_get(animation);
+ alpha = wl_fixed_from_double(alpha);
+ struct hmi_controller_fade *fade = animation->base.user_data;
+ struct link_layer *linklayer = NULL;
+ int32_t is_done = hmi_controller_animation_is_done(&animation->base);
+ int32_t is_visible = !is_done || fade->isFadeIn;
+
+ wl_list_for_each(linklayer, &fade->layer_list, link) {
+ weston_layout_layerSetOpacity(linklayer->layout_layer, alpha);
+ weston_layout_layerSetVisibility(linklayer->layout_layer, is_visible);
+ }
+
+ if (is_done) {
+ hmi_controller_animation_destroy(&animation->base);
+ }
+}
+
+static void
+hmi_controller_anima_move_user_frame(struct hmi_controller_animation_move *animation)
+{
+ struct move_animation_user_data* user_data = animation->base.user_data;
+ struct weston_layout_layer *layer = user_data->layer;
+ int32_t is_done = hmi_controller_animation_is_done(&animation->base);
+
+ int32_t pos[2] = {0};
+ weston_layout_layerGetPosition(layer, pos);
+
+ pos[0] = (int32_t)animation->pos;
+ weston_layout_layerSetPosition(layer, pos);
+
+ if (is_done) {
+ hmi_controller_animation_destroy(&animation->base);
+ }
+}
+
+static void
+hmi_controller_fade_run(uint32_t isFadeIn, struct hmi_controller_fade *fade)
+{
+ double tint = isFadeIn ? 1.0 : 0.0;
+ fade->isFadeIn = isFadeIn;
+
+ if (fade->animation) {
+ hmi_controller_fade_update(fade->animation, tint);
+ } else {
+ fade->animation = hmi_controller_animation_fade_create(
+ 1.0 - tint, tint, 300.0,
+ (hmi_controller_animation_frame_user_func)hmi_controller_anima_fade_user_frame,
+ fade, hmi_controller_fade_animation_destroy);
+
+ animation_set_add_animation(fade->anima_set, &fade->animation->base);
+ }
+}
+
+/**
+ * Internal method to create layer with hmi_controller_layer and add to a screen
+ */
+static void
+create_layer(struct weston_layout_screen *iviscrn,
+ struct hmi_controller_layer *layer)
+{
+ int32_t ret = 0;
+
+ layer->ivilayer = weston_layout_layerCreateWithDimension(layer->id_layer,
+ layer->width, layer->height);
+ assert(layer->ivilayer != NULL);
+
+ ret = weston_layout_screenAddLayer(iviscrn, layer->ivilayer);
+ assert(!ret);
+
+ ret = weston_layout_layerSetDestinationRectangle(layer->ivilayer, layer->x, layer->y,
+ layer->width, layer->height);
+ assert(!ret);
+
+ ret = weston_layout_layerSetVisibility(layer->ivilayer, 1);
+ assert(!ret);
+}
+
+/**
+ * Internal set notification
+ */
+static void
+set_notification_create_surface(struct weston_layout_surface *ivisurf,
+ void *userdata)
+{
+ struct hmi_controller* hmi_ctrl = userdata;
+ struct weston_layout_layer *application_layer = hmi_ctrl->application_layer.ivilayer;
+ int32_t ret = 0;
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ return;
+ }
+
+ ret = weston_layout_layerAddSurface(application_layer, ivisurf);
+ assert(!ret);
+}
+
+static void
+set_notification_remove_surface(struct weston_layout_surface *ivisurf,
+ void *userdata)
+{
+ (void)ivisurf;
+ struct hmi_controller* hmi_ctrl = userdata;
+ switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
+}
+
+static void
+set_notification_configure_surface(struct weston_layout_surface *ivisurf,
+ void *userdata)
+{
+ (void)ivisurf;
+ struct hmi_controller* hmi_ctrl = userdata;
+ switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
+}
+
+/**
+ * A hmi_controller used 4 layers to manage surfaces. The IDs of corresponding layer
+ * are defined in weston.ini. Default scene graph of layers are initialized in
+ * hmi_controller_create
+ */
+static struct hmi_server_setting *
+hmi_server_setting_create(void)
+{
+ struct hmi_server_setting* setting = MEM_ALLOC(sizeof(*setting));
+
+ struct weston_config *config = NULL;
+ config = weston_config_parse("weston.ini");
+
+ struct weston_config_section *shellSection = NULL;
+ shellSection = weston_config_get_section(config, "ivi-shell", NULL, NULL);
+
+ weston_config_section_get_uint(
+ shellSection, "base-layer-id", &setting->base_layer_id, 1000);
+
+ weston_config_section_get_uint(
+ shellSection, "workspace-background-layer-id", &setting->workspace_background_layer_id, 2000);
+
+ weston_config_section_get_uint(
+ shellSection, "workspace-layer-id", &setting->workspace_layer_id, 3000);
+
+ weston_config_section_get_uint(
+ shellSection, "application-layer-id", &setting->application_layer_id, 4000);
+
+ setting->panel_height = 70;
+
+ weston_config_destroy(config);
+
+ return setting;
+}
+
+/**
+ * This is a starting method called from module_init.
+ * This sets up scene graph of layers; base, application, workspace background,
+ * and workspace. These layers are created/added to screen in create_layer
+ *
+ * base: to group surfaces of panel and background
+ * application: to group surfaces of ivi_applications
+ * workspace background: to group a surface of background in workspace
+ * workspace: to group surfaces for launching ivi_applications
+ *
+ * Layers of workspace background and workspace is set to invisible at first.
+ * The properties of it is updated with animation when ivi_hmi_controller_home is
+ * requested.
+ */
+static struct hmi_controller *
+hmi_controller_create(struct weston_compositor *ec)
+{
+ weston_layout_screen_ptr *ppScreen = NULL;
+ struct weston_layout_screen *iviscrn = NULL;
+ uint32_t screen_length = 0;
+ uint32_t screen_width = 0;
+ uint32_t screen_height = 0;
+ int32_t ret = 0;
+ struct link_layer *tmp_link_layer = NULL;
+
+ struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
+ wl_array_init(&hmi_ctrl->ui_widgets);
+ hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
+ hmi_ctrl->hmi_setting = hmi_server_setting_create();
+
+ weston_layout_getScreens(&screen_length, &ppScreen);
+
+ iviscrn = ppScreen[0];
+
+ weston_layout_getScreenResolution(iviscrn, &screen_width, &screen_height);
+ assert(!ret);
+
+ /* init base layer*/
+ hmi_ctrl->base_layer.x = 0;
+ hmi_ctrl->base_layer.y = 0;
+ hmi_ctrl->base_layer.width = screen_width;
+ hmi_ctrl->base_layer.height = screen_height;
+ hmi_ctrl->base_layer.id_layer = hmi_ctrl->hmi_setting->base_layer_id;
+
+ create_layer(iviscrn, &hmi_ctrl->base_layer);
+
+ uint32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
+
+
+ /* init application layer */
+ hmi_ctrl->application_layer.x = 0;
+ hmi_ctrl->application_layer.y = 0;
+ hmi_ctrl->application_layer.width = screen_width;
+ hmi_ctrl->application_layer.height = screen_height - panel_height;
+ hmi_ctrl->application_layer.id_layer = hmi_ctrl->hmi_setting->application_layer_id;
+
+ create_layer(iviscrn, &hmi_ctrl->application_layer);
+
+ /* init workspace background layer */
+ hmi_ctrl->workspace_background_layer.x = 0;
+ hmi_ctrl->workspace_background_layer.y = 0;
+ hmi_ctrl->workspace_background_layer.width = screen_width;
+ hmi_ctrl->workspace_background_layer.height = screen_height - panel_height;
+
+ hmi_ctrl->workspace_background_layer.id_layer =
+ hmi_ctrl->hmi_setting->workspace_background_layer_id;
+
+ create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
+ weston_layout_layerSetOpacity(hmi_ctrl->workspace_background_layer.ivilayer, 0);
+ weston_layout_layerSetVisibility(hmi_ctrl->workspace_background_layer.ivilayer, 0);
+
+ /* init workspace layer */
+ hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
+ hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
+ hmi_ctrl->workspace_layer.width = hmi_ctrl->workspace_background_layer.width;
+ hmi_ctrl->workspace_layer.height = hmi_ctrl->workspace_background_layer.height;
+ hmi_ctrl->workspace_layer.id_layer = hmi_ctrl->hmi_setting->workspace_layer_id;
+
+ create_layer(iviscrn, &hmi_ctrl->workspace_layer);
+ weston_layout_layerSetOpacity(hmi_ctrl->workspace_layer.ivilayer, 0);
+ weston_layout_layerSetVisibility(hmi_ctrl->workspace_layer.ivilayer, 0);
+
+ /* set up animation to workspace background and workspace */
+ hmi_ctrl->anima_set = animation_set_create(ec);
+
+ wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
+ tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
+ tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
+ wl_list_insert(&hmi_ctrl->workspace_fade.layer_list, &tmp_link_layer->link);
+ tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
+ tmp_link_layer->layout_layer = hmi_ctrl->workspace_background_layer.ivilayer;
+ wl_list_insert(&hmi_ctrl->workspace_fade.layer_list, &tmp_link_layer->link);
+ hmi_ctrl->workspace_fade.anima_set = hmi_ctrl->anima_set;
+
+ weston_layout_setNotificationCreateSurface(set_notification_create_surface, hmi_ctrl);
+ weston_layout_setNotificationRemoveSurface(set_notification_remove_surface, hmi_ctrl);
+ weston_layout_setNotificationConfigureSurface(set_notification_configure_surface, hmi_ctrl);
+
+ free(ppScreen);
+ ppScreen = NULL;
+
+ return hmi_ctrl;
+}
+
+/**
+ * Implementations of ivi-hmi-controller.xml
+ */
+
+/**
+ * A surface drawing background is identified by id_surface.
+ * Properties of the surface is set by using weston_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * UI layer is used to add this surface.
+ */
+static void
+ivi_hmi_controller_set_background(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id_surface)
+
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
+ const uint32_t dstx = hmi_ctrl->application_layer.x;
+ const uint32_t dsty = hmi_ctrl->application_layer.y;
+ const uint32_t width = hmi_ctrl->application_layer.width;
+ const uint32_t height = hmi_ctrl->application_layer.height;
+ uint32_t ret = 0;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ ivisurf = weston_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = weston_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetDestinationRectangle(ivisurf,
+ dstx, dsty, width, height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ weston_layout_commitChanges();
+}
+
+/**
+ * A surface drawing panel is identified by id_surface.
+ * Properties of the surface is set by using weston_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * UI layer is used to add this surface.
+ */
+static void
+ivi_hmi_controller_set_panel(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id_surface)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
+ const uint32_t width = hmi_ctrl->base_layer.width;
+ uint32_t ret = 0;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ ivisurf = weston_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = weston_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+ uint32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
+ const uint32_t dstx = 0;
+ const uint32_t dsty = hmi_ctrl->base_layer.height - panel_height;
+
+ ret = weston_layout_surfaceSetDestinationRectangle(
+ ivisurf, dstx, dsty, width, panel_height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ weston_layout_commitChanges();
+}
+
+/**
+ * A surface drawing buttons in panel is identified by id_surface. It can set
+ * several buttons. Properties of the surface is set by using weston_layout
+ * APIs according to the scene graph of UI defined in hmi_controller_create.
+ * Additionally, the position of it is shifted to right when new one is requested.
+ *
+ * UI layer is used to add these surfaces.
+ */
+static void
+ivi_hmi_controller_set_button(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id_surface, uint32_t number)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
+ const uint32_t width = 48;
+ const uint32_t height = 48;
+ uint32_t ret = 0;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ ivisurf = weston_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = weston_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+
+ uint32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
+
+ const uint32_t dstx = (60 * number) + 15;
+ const uint32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
+
+ ret = weston_layout_surfaceSetDestinationRectangle(
+ ivisurf,dstx, dsty, width, height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ weston_layout_commitChanges();
+}
+
+/**
+ * A surface drawing home button in panel is identified by id_surface.
+ * Properties of the surface is set by using weston_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * UI layer is used to add these surfaces.
+ */
+static void
+ivi_hmi_controller_set_home_button(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id_surface)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
+ uint32_t ret = 0;
+ uint32_t size = 48;
+ uint32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
+ const uint32_t dstx = (hmi_ctrl->base_layer.width - size) / 2;
+ const uint32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ ivisurf = weston_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = weston_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetDestinationRectangle(
+ ivisurf, dstx, dsty, size, size);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ weston_layout_commitChanges();
+ hmi_ctrl->is_initialized = 1;
+}
+
+/**
+ * A surface drawing background of workspace is identified by id_surface.
+ * Properties of the surface is set by using weston_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * A layer of workspace_background is used to add this surface.
+ */
+static void
+ivi_hmi_controller_set_workspacebackground(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id_surface)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct weston_layout_surface *ivisurf = NULL;
+ struct weston_layout_layer *ivilayer = NULL;
+ ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ const uint32_t width = hmi_ctrl->workspace_background_layer.width;
+ const uint32_t height = hmi_ctrl->workspace_background_layer.height;
+ uint32_t ret = 0;
+
+ ivisurf = weston_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = weston_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetDestinationRectangle(ivisurf,
+ 0, 0, width, height);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ weston_layout_commitChanges();
+}
+
+/**
+ * A list of surfaces drawing launchers in workspace is identified by id_surfaces.
+ * Properties of the surface is set by using weston_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * The workspace can have several pages to group surfaces of launcher. Each call
+ * of this interface increments a number of page to add a group of surfaces
+ */
+static void
+ivi_hmi_controller_add_launchers(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_array *surface_ids,
+ uint32_t icon_size)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct weston_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
+ uint32_t minspace_x = 10;
+ uint32_t minspace_y = minspace_x;
+
+ uint32_t width = hmi_ctrl->workspace_layer.width;
+ uint32_t height = hmi_ctrl->workspace_layer.height;
+
+ uint32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
+ uint32_t space_x = (uint32_t)((width - x_count * icon_size) / (1.0 + x_count));
+ float fcell_size_x = icon_size + space_x;
+
+ uint32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
+ uint32_t space_y = (uint32_t)((height - y_count * icon_size) / (1.0 + y_count));
+ float fcell_size_y = icon_size + space_y;
+
+ if (0 == x_count) {
+ x_count = 1;
+ }
+
+ if (0 == y_count) {
+ y_count = 1;
+ }
+
+ hmi_ctrl->workspace_count++;
+
+ uint32_t *surface_id = NULL;
+ uint32_t nx = 0;
+ uint32_t ny = 0;
+
+ wl_array_for_each(surface_id, surface_ids) {
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = *surface_id;
+
+ if (y_count == ny) {
+ ny = 0;
+ hmi_ctrl->workspace_count++;
+ }
+
+ uint32_t x = (uint32_t)(nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x);
+ uint32_t y = (uint32_t)(ny * fcell_size_y + space_y) ;
+
+ struct weston_layout_surface* layout_surface = NULL;
+ layout_surface = weston_layout_getSurfaceFromId(*surface_id);
+ assert(layout_surface);
+
+ uint32_t ret = 0;
+ ret = weston_layout_layerAddSurface(layer, layout_surface);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetDestinationRectangle(
+ layout_surface, x, y, icon_size, icon_size);
+ assert(!ret);
+
+ ret = weston_layout_surfaceSetVisibility(layout_surface, 1);
+ assert(!ret);
+
+ nx++;
+
+ if (x_count == nx) {
+ ny++;
+ nx = 0;
+ }
+ }
+
+ weston_layout_commitChanges();
+}
+
+/**
+ * Implementation of request and event of ivi_hmi_controller_workspace_control
+ * and controlling workspace.
+ *
+ * When motion of input is detected in a surface of workspace background,
+ * ivi_hmi_controller_workspace_control shall be invoked and to start controlling of
+ * workspace. The workspace has several pages to show several groups of applications.
+ * The workspace is slid by using weston-layout to select a a page in layer_set_pos
+ * according to motion. When motion finished, e.g. touch up detected, control is
+ * terminated and event:ivi_hmi_controller_workspace_control is notified.
+ */
+struct pointer_grab {
+ struct weston_pointer_grab grab;
+ struct weston_layout_layer *layer;
+ struct wl_resource *resource;
+};
+
+struct touch_grab {
+ struct weston_touch_grab grab;
+ struct weston_layout_layer *layer;
+ struct wl_resource *resource;
+};
+
+struct move_grab {
+ wl_fixed_t dst[2];
+ wl_fixed_t rgn[2][2];
+ double v[2];
+ struct timespec start_time;
+ struct timespec pre_time;
+ wl_fixed_t start_pos[2];
+ wl_fixed_t pos[2];
+ int32_t is_moved;
+};
+
+struct pointer_move_grab {
+ struct pointer_grab base;
+ struct move_grab move;
+};
+
+struct touch_move_grab {
+ struct touch_grab base;
+ struct move_grab move;
+ int32_t is_active;
+};
+
+static void
+pointer_grab_start(struct pointer_grab *grab,
+ struct weston_layout_layer *layer,
+ const struct weston_pointer_grab_interface *interface,
+ struct weston_pointer *pointer)
+{
+ grab->grab.interface = interface;
+ grab->layer = layer;
+ weston_pointer_start_grab(pointer, &grab->grab);
+}
+
+static void
+touch_grab_start(struct touch_grab *grab,
+ struct weston_layout_layer *layer,
+ const struct weston_touch_grab_interface *interface,
+ struct weston_touch* touch)
+{
+ grab->grab.interface = interface;
+ grab->layer = layer;
+ weston_touch_start_grab(touch, &grab->grab);
+}
+
+static int32_t
+range_val(int32_t val, int32_t min, int32_t max)
+{
+ if (val < min) {
+ return min;
+ }
+
+ if (max < val) {
+ return max;
+ }
+
+ return val;
+}
+
+static void
+hmi_controller_move_animation_destroy(struct hmi_controller_animation *animation)
+{
+ struct move_animation_user_data *user_data = animation->user_data;
+ if (animation == &user_data->hmi_ctrl->workspace_swipe_animation->base) {
+ user_data->hmi_ctrl->workspace_swipe_animation = NULL;
+ }
+
+ animation_set_remove_animation(user_data->anima_set, animation);
+ free(animation->user_data);
+ animation->user_data = NULL;
+}
+
+static void
+move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
+ wl_fixed_t grab_x, struct weston_layout_layer *layer)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ int32_t width = (int32_t)hmi_ctrl->workspace_background_layer.width;
+
+ struct timespec time = {0};
+ clock_gettime(CLOCK_MONOTONIC, &time);
+
+ double grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
+ 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
+
+ double from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
+ 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
+
+ double pointer_v = move->v[0];
+
+ if (200 < from_motion_time) {
+ pointer_v = 0.0;
+ }
+
+ int32_t is_flick = grab_time < 400 &&
+ 0.4 < fabs(pointer_v);
+
+ int32_t pos[2] = {0};
+ weston_layout_layerGetPosition(layer, pos);
+
+ int page_no = 0;
+
+ if (is_flick) {
+ int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
+ page_no = (-orgx + width / 2) / width;
+
+ if (pointer_v < 0.0) {
+ page_no++;
+ }else {
+ page_no--;
+ }
+ }else {
+ page_no = (-pos[0] + width / 2) / width;
+ }
+
+ page_no = range_val(page_no, 0, hmi_ctrl->workspace_count - 1);
+ double end_pos = -page_no * width;
+
+ double dst = fabs(end_pos - pos[0]);
+ double max_time = 0.5 * 1e+3;
+ double v = dst / max_time;
+
+ double vmin = 1000 * 1e-3;
+ if (v < vmin ) {
+ v = vmin;
+ }
+
+ double v0 = 0.0;
+ if (pos[0] < end_pos) {
+ v0 = v;
+ } else {
+ v0 = -v;
+ }
+
+ struct move_animation_user_data *animation_user_data = NULL;
+ animation_user_data = MEM_ALLOC(sizeof(*animation_user_data));
+ animation_user_data->layer = layer;
+ animation_user_data->anima_set = hmi_ctrl->anima_set;
+ animation_user_data->hmi_ctrl = hmi_ctrl;
+
+ struct hmi_controller_animation_move* animation = NULL;
+ animation = hmi_controller_animation_move_create(
+ pos[0], end_pos, v0, v0,
+ (hmi_controller_animation_frame_user_func)hmi_controller_anima_move_user_frame,
+ animation_user_data, hmi_controller_move_animation_destroy);
+
+ hmi_ctrl->workspace_swipe_animation = animation;
+ animation_set_add_animation(hmi_ctrl->anima_set, &animation->base);
+
+ ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
+}
+
+static void
+pointer_move_workspace_grab_end(struct pointer_grab *grab)
+{
+ struct pointer_move_grab *pnt_move_grab = (struct pointer_move_grab *) grab;
+ struct weston_layout_layer *layer = pnt_move_grab->base.layer;
+
+ move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
+ grab->grab.pointer->grab_x, layer);
+
+ weston_pointer_end_grab(grab->grab.pointer);
+}
+
+static void
+touch_move_workspace_grab_end(struct touch_grab *grab)
+{
+ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *) grab;
+ struct weston_layout_layer *layer = tch_move_grab->base.layer;
+
+ move_workspace_grab_end(&tch_move_grab->move, grab->resource,
+ grab->grab.touch->grab_x, layer);
+
+ weston_touch_end_grab(grab->grab.touch);
+}
+
+static void
+pointer_noop_grab_focus(struct weston_pointer_grab *grab)
+{
+}
+
+static void
+move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
+{
+ struct timespec timestamp = {0};
+ clock_gettime(CLOCK_MONOTONIC, &timestamp);
+
+ double dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
+ 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
+
+ if (dt < 1e-6) {
+ dt = 1e-6;
+ }
+
+ move->pre_time = timestamp;
+
+ int32_t ii = 0;
+ for (ii = 0; ii < 2; ii++) {
+ wl_fixed_t prepos = move->pos[ii];
+ move->pos[ii] = pointer[ii] + move->dst[ii];
+
+ if (move->pos[ii] < move->rgn[0][ii]) {
+ move->pos[ii] = move->rgn[0][ii];
+ move->dst[ii] = move->pos[ii] - pointer[ii];
+ } else if (move->rgn[1][ii] < move->pos[ii]) {
+ move->pos[ii] = move->rgn[1][ii];
+ move->dst[ii] = move->pos[ii] - pointer[ii];
+ }
+
+ move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
+
+ if (!move->is_moved &&
+ 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii])) {
+ move->is_moved = 1;
+ }
+ }
+}
+
+static void
+layer_set_pos(struct weston_layout_layer *layer, wl_fixed_t pos[2])
+{
+ int32_t layout_pos[2] = {0};
+ layout_pos[0] = wl_fixed_to_int(pos[0]);
+ layout_pos[1] = wl_fixed_to_int(pos[1]);
+ weston_layout_layerSetPosition(layer, layout_pos);
+ weston_layout_commitChanges();
+}
+
+static void
+pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
+ wl_fixed_t x, wl_fixed_t y)
+{
+ struct pointer_move_grab *pnt_move_grab = (struct pointer_move_grab *) grab;
+ wl_fixed_t pointer_pos[2] = {x, y};
+ move_grab_update(&pnt_move_grab->move, pointer_pos);
+ layer_set_pos(pnt_move_grab->base.layer, pnt_move_grab->move.pos);
+ weston_pointer_move(pnt_move_grab->base.grab.pointer, x, y);
+}
+
+static void
+touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
+ int touch_id, wl_fixed_t x, wl_fixed_t y)
+{
+ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *) grab;
+
+ if (!tch_move_grab->is_active) {
+ return;
+ }
+
+ wl_fixed_t pointer_pos[2] = {grab->touch->grab_x, grab->touch->grab_y};
+ move_grab_update(&tch_move_grab->move, pointer_pos);
+ layer_set_pos(tch_move_grab->base.layer, tch_move_grab->move.pos);
+}
+
+static void
+pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
+ uint32_t time, uint32_t button,
+ uint32_t state_w)
+{
+ if (BTN_LEFT == button &&
+ WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
+ struct pointer_grab *pg = (struct pointer_grab *)grab;
+ pointer_move_workspace_grab_end(pg);
+ free(grab);
+ }
+}
+
+static void
+touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
+ int touch_id, wl_fixed_t sx, wl_fixed_t sy)
+{
+}
+
+static void
+touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
+{
+ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
+
+ if (0 == touch_id) {
+ tch_move_grab->is_active = 0;
+ }
+
+ if (0 == grab->touch->num_tp) {
+ touch_move_workspace_grab_end(&tch_move_grab->base);
+ free(grab);
+ }
+}
+
+static void
+pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
+{
+ struct pointer_grab *pg = (struct pointer_grab *)grab;
+ pointer_move_workspace_grab_end(pg);
+ free(grab);
+}
+
+static void
+touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
+{
+ struct touch_grab *tg = (struct touch_grab *)grab;
+ touch_move_workspace_grab_end(tg);
+ free(grab);
+}
+
+static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
+ pointer_noop_grab_focus,
+ pointer_move_grab_motion,
+ pointer_move_workspace_grab_button,
+ pointer_move_workspace_grab_cancel
+};
+
+static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
+ touch_nope_grab_down,
+ touch_move_workspace_grab_up,
+ touch_move_grab_motion,
+ touch_move_workspace_grab_cancel
+};
+
+enum HMI_GRAB_DEVICE
+{
+ HMI_GRAB_DEVICE_NONE,
+ HMI_GRAB_DEVICE_POINTER,
+ HMI_GRAB_DEVICE_TOUCH
+};
+
+static enum HMI_GRAB_DEVICE
+get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
+{
+ if (seat->pointer &&
+ seat->pointer->focus &&
+ seat->pointer->button_count &&
+ seat->pointer->grab_serial == serial) {
+ return HMI_GRAB_DEVICE_POINTER;
+ }
+
+ if (seat->touch &&
+ seat->touch->focus &&
+ seat->touch->grab_serial) {
+ return HMI_GRAB_DEVICE_TOUCH;
+ }
+
+ return HMI_GRAB_DEVICE_NONE;
+}
+
+static void
+move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
+ wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
+ struct wl_resource* resource)
+{
+ clock_gettime(CLOCK_MONOTONIC, &move->start_time);
+ move->pre_time = move->start_time;
+ move->pos[0] = start_pos[0];
+ move->pos[1] = start_pos[1];
+ move->start_pos[0] = start_pos[0];
+ move->start_pos[1] = start_pos[1];
+ move->dst[0] = start_pos[0] - grab_pos[0];
+ move->dst[1] = start_pos[1] - grab_pos[1];
+ memcpy(move->rgn, rgn, sizeof(move->rgn));
+}
+
+static void
+move_grab_init_workspace(struct move_grab* move,
+ wl_fixed_t grab_x, wl_fixed_t grab_y,
+ struct wl_resource *resource)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct weston_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
+ int32_t workspace_count = hmi_ctrl->workspace_count;
+ int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
+ int32_t layer_pos[2] = {0};
+ weston_layout_layerGetPosition(layer, layer_pos);
+
+ wl_fixed_t start_pos[2] = {0};
+ start_pos[0] = wl_fixed_from_int(layer_pos[0]);
+ start_pos[1] = wl_fixed_from_int(layer_pos[1]);
+
+ wl_fixed_t rgn[2][2] = {{0}};
+ rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
+
+ rgn[0][1] = wl_fixed_from_int(0);
+ rgn[1][0] = wl_fixed_from_int(0);
+ rgn[1][1] = wl_fixed_from_int(0);
+
+ wl_fixed_t grab_pos[2] = {grab_x, grab_y};
+
+ move_grab_init(move, start_pos, grab_pos, rgn, resource);
+}
+
+static struct pointer_move_grab *
+create_workspace_pointer_move(struct weston_pointer *pointer, struct wl_resource* resource)
+{
+ struct pointer_move_grab *pnt_move_grab = MEM_ALLOC(sizeof(*pnt_move_grab));
+ pnt_move_grab->base.resource = resource;
+ move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x, pointer->grab_y, resource);
+ return pnt_move_grab;
+}
+
+static struct touch_move_grab *
+create_workspace_touch_move(struct weston_touch *touch, struct wl_resource* resource)
+{
+ struct touch_move_grab *tch_move_grab = MEM_ALLOC(sizeof(*tch_move_grab));
+ tch_move_grab->base.resource = resource;
+ tch_move_grab->is_active = 1;
+ move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,touch->grab_y, resource);
+ return tch_move_grab;
+}
+
+static void
+ivi_hmi_controller_workspace_control(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat_resource,
+ uint32_t serial)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+
+ if (hmi_ctrl->workspace_count < 2) {
+ return;
+ }
+
+ struct weston_seat* seat = wl_resource_get_user_data(seat_resource);
+ enum HMI_GRAB_DEVICE device = get_hmi_grab_device(seat, serial);
+
+ if (HMI_GRAB_DEVICE_POINTER != device &&
+ HMI_GRAB_DEVICE_TOUCH != device) {
+ return;
+ }
+
+ if (hmi_ctrl->workspace_swipe_animation) {
+ hmi_controller_animation_destroy(&hmi_ctrl->workspace_swipe_animation->base);
+ }
+
+ struct weston_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
+ struct pointer_move_grab *pnt_move_grab = NULL;
+ struct touch_move_grab *tch_move_grab = NULL;
+
+ switch (device) {
+ case HMI_GRAB_DEVICE_POINTER:
+ pnt_move_grab = create_workspace_pointer_move(seat->pointer, resource);
+
+ pointer_grab_start(
+ &pnt_move_grab->base, layer, &pointer_move_grab_workspace_interface,
+ seat->pointer);
+ break;
+
+ case HMI_GRAB_DEVICE_TOUCH:
+ tch_move_grab = create_workspace_touch_move(seat->touch, resource);
+
+ touch_grab_start(
+ &tch_move_grab->base, layer, &touch_move_grab_workspace_interface,
+ seat->touch);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * Implementation of switch_mode
+ */
+static void
+ivi_hmi_controller_switch_mode(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t layout_mode)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ switch_mode(hmi_ctrl, layout_mode);
+}
+
+/**
+ * Implementation of on/off displaying workspace and workspace background layers.
+ */
+static void
+ivi_hmi_controller_home(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t home)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+
+ if ((IVI_HMI_CONTROLLER_HOME_ON == home && !hmi_ctrl->workspace_fade.isFadeIn) ||
+ (IVI_HMI_CONTROLLER_HOME_OFF == home && hmi_ctrl->workspace_fade.isFadeIn)) {
+
+ uint32_t isFadeIn = !hmi_ctrl->workspace_fade.isFadeIn;
+ hmi_controller_fade_run(isFadeIn, &hmi_ctrl->workspace_fade);
+ }
+}
+
+/**
+ * binding ivi-hmi-controller implementation
+ */
+static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
+ ivi_hmi_controller_set_background,
+ ivi_hmi_controller_set_panel,
+ ivi_hmi_controller_set_button,
+ ivi_hmi_controller_set_home_button,
+ ivi_hmi_controller_set_workspacebackground,
+ ivi_hmi_controller_add_launchers,
+ ivi_hmi_controller_workspace_control,
+ ivi_hmi_controller_switch_mode,
+ ivi_hmi_controller_home
+};
+
+static void
+unbind_hmi_controller(struct wl_resource *resource)
+{
+}
+
+static void
+bind_hmi_controller(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct wl_resource *resource = NULL;
+
+ resource = wl_resource_create(
+ client, &ivi_hmi_controller_interface, 1, id);
+
+ wl_resource_set_implementation(
+ resource, &ivi_hmi_controller_implementation,
+ data, unbind_hmi_controller);
+}
+
+static void
+launch_hmi_client(void *data)
+{
+ hmi_client_start();
+}
+
+/*****************************************************************************
+ * exported functions
+ ****************************************************************************/
+
+WL_EXPORT int
+module_init(struct weston_compositor *ec,
+ int *argc, char *argv[])
+{
+ struct hmi_controller *hmi_ctrl = hmi_controller_create(ec);
+
+ if (wl_global_create(ec->wl_display,
+ &ivi_hmi_controller_interface, 1,
+ hmi_ctrl, bind_hmi_controller) == NULL) {
+ return -1;
+ }
+
+ struct wl_event_loop *loop = wl_display_get_event_loop(ec->wl_display);
+ wl_event_loop_add_idle(loop, launch_hmi_client, ec);
+
+ return 0;
+}
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:03:03 UTC
Permalink
This is launched from hmi-controller by using hmi_client_start and create a
pthread.

The basic flow is as followed,
1/ create pthread
2/ read configuration from weston.ini.
3/ draw png file to surface according to configuration of weston.ini
4/ set up UI by using ivi-hmi-controller protocol
5/ Enter event loop
6/ If a surface receives touch/pointer event, followings are invoked according
to type of event and surface
6-1/ If a surface to launch ivi_application receive touch up, it execs
ivi-application configured in weston.ini.
6-2/ If a surface to switch layout mode receive touch up, it sends a request,
ivi_hmi_controller_switch_mode, to hmi-controller.
6-3/ If a surface to show workspace having launchers, it sends a request,
ivi_hmi_controller_home, to hmi-controller.
6-4/ If touch down events happens in workspace,
ivi_hmi_controller_workspace_control is sent to slide workspace.
When control finished, event: ivi_hmi_controller_workspace_end_control
is received.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
ivi-shell/hmi-controller-homescreen.c | 1370 +++++++++++++++++++++++++++++++++
ivi-shell/hmi-controller-homescreen.h | 36 +
2 files changed, 1406 insertions(+)
create mode 100644 ivi-shell/hmi-controller-homescreen.c
create mode 100644 ivi-shell/hmi-controller-homescreen.h

diff --git a/ivi-shell/hmi-controller-homescreen.c b/ivi-shell/hmi-controller-homescreen.c
new file mode 100644
index 0000000..51f6c75
--- /dev/null
+++ b/ivi-shell/hmi-controller-homescreen.c
@@ -0,0 +1,1370 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <getopt.h>
+#include <pthread.h>
+#include <wayland-cursor.h>
+#include "hmi-controller-homescreen.h"
+#include "../shared/cairo-util.h"
+#include "../shared/config-parser.h"
+#include "ivi-application-client-protocol.h"
+#include "ivi-hmi-controller-client-protocol.h"
+
+/**
+ * A reference implementation how to use ivi-hmi-controller interface to interact
+ * with hmi-controller. This is launched from hmi-controller by using
+ * hmi_client_start and create a pthread.
+ *
+ * The basic flow is as followed,
+ * 1/ create pthread
+ * 2/ read configuration from weston.ini.
+ * 3/ draw png file to surface according to configuration of weston.ini
+ * 4/ set up UI by using ivi-hmi-controller protocol
+ * 5/ Enter event loop
+ * 6/ If a surface receives touch/pointer event, followings are invoked according
+ * to type of event and surface
+ * 6-1/ If a surface to launch ivi_application receive touch up, it execs
+ * ivi-application configured in weston.ini.
+ * 6-2/ If a surface to switch layout mode receive touch up, it sends a request,
+ * ivi_hmi_controller_switch_mode, to hmi-controller.
+ * 6-3/ If a surface to show workspace having launchers, it sends a request,
+ * ivi_hmi_controller_home, to hmi-controller.
+ * 6-4/ If touch down events happens in workspace,
+ * ivi_hmi_controller_workspace_control is sent to slide workspace.
+ * When control finished, event: ivi_hmi_controller_workspace_end_control
+ * is received.
+ */
+
+/*****************************************************************************
+ * structure, globals
+ ****************************************************************************/
+enum cursor_type {
+ CURSOR_BOTTOM_LEFT,
+ CURSOR_BOTTOM_RIGHT,
+ CURSOR_BOTTOM,
+ CURSOR_DRAGGING,
+ CURSOR_LEFT_PTR,
+ CURSOR_LEFT,
+ CURSOR_RIGHT,
+ CURSOR_TOP_LEFT,
+ CURSOR_TOP_RIGHT,
+ CURSOR_TOP,
+ CURSOR_IBEAM,
+ CURSOR_HAND1,
+ CURSOR_WATCH,
+
+ CURSOR_BLANK
+};
+struct wlContextCommon {
+ struct wl_display *wlDisplay;
+ struct wl_registry *wlRegistry;
+ struct wl_compositor *wlCompositor;
+ struct wl_shm *wlShm;
+ struct wl_seat *wlSeat;
+ struct wl_pointer *wlPointer;
+ struct wl_touch *wlTouch;
+ struct ivi_application *iviApplication;
+ struct ivi_hmi_controller *hmiCtrl;
+ struct hmi_homescreen_setting *hmi_setting;
+ struct wl_list *list_wlContextStruct;
+ struct wl_surface *enterSurface;
+ int32_t is_home_on;
+ struct wl_cursor_theme *cursor_theme;
+ struct wl_cursor **cursors;
+ struct wl_surface *pointer_surface;
+ enum cursor_type current_cursor;
+ uint32_t enter_serial;
+};
+
+struct wlContextStruct {
+ struct wlContextCommon cmm;
+ struct wl_surface *wlSurface;
+ struct wl_buffer *wlBuffer;
+ uint32_t formats;
+ cairo_surface_t *ctx_image;
+ void *data;
+ uint32_t id_surface;
+ struct wl_list link;
+};
+
+struct
+hmi_homescreen_srf {
+ uint32_t id;
+ char *filePath;
+ uint32_t color;
+};
+
+struct
+hmi_homescreen_workspace {
+ struct wl_array launcher_id_array;
+ struct wl_list link;
+};
+
+struct
+hmi_homescreen_launcher {
+ uint32_t icon_surface_id;
+ uint32_t workspace_id;
+ char* icon;
+ char* path;
+ struct wl_list link;
+};
+
+struct
+hmi_homescreen_setting {
+ struct hmi_homescreen_srf background;
+ struct hmi_homescreen_srf panel;
+ struct hmi_homescreen_srf tiling;
+ struct hmi_homescreen_srf sidebyside;
+ struct hmi_homescreen_srf fullscreen;
+ struct hmi_homescreen_srf random;
+ struct hmi_homescreen_srf home;
+ struct hmi_homescreen_srf workspace_background;
+
+ struct wl_list workspace_list;
+ struct wl_list launcher_list;
+
+ char *cursor_theme;
+ int32_t cursor_size;
+};
+
+volatile int gRun = 0;
+
+static void *
+fail_on_null(void *p, size_t size, char* file, int32_t line)
+{
+ if (size && !p) {
+ fprintf(stderr, "%s(%d) %zd: out of memory\n", file, line, size);
+ exit(EXIT_FAILURE);
+ }
+
+ return p;
+}
+
+static void *
+mem_alloc(size_t size, char* file, int32_t line)
+{
+ return fail_on_null(calloc(1, size), size, file, line);
+}
+
+#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+/*****************************************************************************
+ * Event Handler
+ ****************************************************************************/
+
+static void
+shm_format(void* data, struct wl_shm* pWlShm, uint32_t format)
+{
+ struct wlContextStruct* pDsp = data;
+ pDsp->formats |= (1 << format);
+}
+
+static struct wl_shm_listener shm_listenter = {
+ shm_format
+};
+
+static int32_t
+getIdOfWlSurface(struct wlContextCommon *pCtx, struct wl_surface *wlSurface)
+{
+ if (NULL == pCtx ||
+ NULL == wlSurface ) {
+ return 0;
+ }
+
+ struct wlContextStruct* pWlCtxSt = NULL;
+ wl_list_for_each(pWlCtxSt, pCtx->list_wlContextStruct, link) {
+ if (pWlCtxSt->wlSurface == wlSurface) {
+ return pWlCtxSt->id_surface;
+ }
+ continue;
+ }
+ return -1;
+}
+
+static void
+set_pointer_image(struct wlContextCommon *pCtx, uint32_t index)
+{
+ if (!pCtx->wlPointer ||
+ !pCtx->cursors) {
+ return;
+ }
+
+ if (CURSOR_BLANK == pCtx->current_cursor) {
+ wl_pointer_set_cursor(pCtx->wlPointer, pCtx->enter_serial,
+ NULL, 0, 0);
+ return;
+ }
+
+ struct wl_cursor *cursor = pCtx->cursors[pCtx->current_cursor];
+ if (!cursor) {
+ return;
+ }
+
+ if (cursor->image_count <= index) {
+ fprintf(stderr, "cursor index out of range\n");
+ return;
+ }
+
+ struct wl_cursor_image *image = cursor->images[index];
+ struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+
+ if (!buffer) {
+ return;
+ }
+
+ wl_pointer_set_cursor(pCtx->wlPointer, pCtx->enter_serial,
+ pCtx->pointer_surface,
+ image->hotspot_x, image->hotspot_y);
+
+ wl_surface_attach(pCtx->pointer_surface, buffer, 0, 0);
+
+ wl_surface_damage(pCtx->pointer_surface, 0, 0,
+ image->width, image->height);
+
+ wl_surface_commit(pCtx->pointer_surface);
+}
+
+static void
+PointerHandleEnter(void* data, struct wl_pointer* wlPointer, uint32_t serial,
+ struct wl_surface* wlSurface, wl_fixed_t sx, wl_fixed_t sy)
+{
+ (void)wlPointer;
+ (void)serial;
+
+ struct wlContextCommon *pCtx = data;
+ pCtx->enter_serial = serial;
+ pCtx->enterSurface = wlSurface;
+ set_pointer_image(pCtx, 0);
+#ifdef _DEBUG
+ printf("ENTER PointerHandleEnter: x(%d), y(%d)\n", sx, sy);
+#endif
+}
+
+static void
+PointerHandleLeave(void* data, struct wl_pointer* wlPointer, uint32_t serial,
+ struct wl_surface* wlSurface)
+{
+ (void)wlPointer;
+ (void)wlSurface;
+
+ struct wlContextCommon *pCtx = data;
+ pCtx->enterSurface = NULL;
+
+#ifdef _DEBUG
+ printf("ENTER PointerHandleLeave: serial(%d)\n", serial);
+#endif
+}
+
+static void
+PointerHandleMotion(void* data, struct wl_pointer* wlPointer, uint32_t time,
+ wl_fixed_t sx, wl_fixed_t sy)
+{
+ (void)data;
+ (void)wlPointer;
+ (void)time;
+
+#ifdef _DEBUG
+ printf("ENTER PointerHandleMotion: x(%d), y(%d)\n", gPointerX, gPointerY);
+#endif
+}
+
+/**
+ * if a surface assigned as launcher receives touch-off event, invoking
+ * ivi-application which configured in weston.ini with path to binary.
+ */
+extern char **environ; /*defied by libc */
+
+static pid_t execute_process(char* path, char *argv[])
+{
+ pid_t pid = fork();
+ if (pid < 0) {
+ fprintf(stderr, "Failed to fork\n");
+ }
+
+ if (pid) {
+ return pid;
+ }
+
+ if (-1 == execve(path, argv, environ)) {
+ fprintf(stderr, "Failed to execve %s\n", path);
+ exit(1);
+ }
+
+ return pid;
+}
+
+static int32_t
+launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)
+{
+ struct hmi_homescreen_launcher *launcher = NULL;
+
+ wl_list_for_each(launcher, launcher_list, link) {
+ if (surfaceId != launcher->icon_surface_id) {
+ continue;
+ }
+
+ char *argv[] = {NULL};
+ execute_process(launcher->path, argv);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * is-method to identify a surface set as launcher in workspace or workspace
+ * itself. This is-method is used to decide whether request;
+ * ivi_hmi_controller_workspace_control is sent or not.
+ */
+static int32_t
+isWorkspaceSurface(uint32_t id, struct hmi_homescreen_setting *hmi_setting)
+{
+ if (id == hmi_setting->workspace_background.id) {
+ return 1;
+ }
+
+ struct hmi_homescreen_launcher *launcher = NULL;
+ wl_list_for_each(launcher, &hmi_setting->launcher_list, link) {
+ if (id == launcher->icon_surface_id) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Decide which request is sent to hmi-controller
+ */
+static void
+touch_up(struct ivi_hmi_controller *hmi_ctrl, uint32_t id_surface,
+ int32_t *is_home_on, struct hmi_homescreen_setting* hmi_setting)
+{
+ if (launcher_button(id_surface, &hmi_setting->launcher_list)) {
+ *is_home_on = 0;
+ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);
+ } else if (id_surface == hmi_setting->tiling.id) {
+ ivi_hmi_controller_switch_mode(
+ hmi_ctrl, IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING);
+ } else if (id_surface == hmi_setting->sidebyside.id) {
+ ivi_hmi_controller_switch_mode(
+ hmi_ctrl, IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE);
+ } else if (id_surface == hmi_setting->fullscreen.id) {
+ ivi_hmi_controller_switch_mode(
+ hmi_ctrl, IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN);
+ } else if (id_surface == hmi_setting->random.id) {
+ ivi_hmi_controller_switch_mode(
+ hmi_ctrl, IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM);
+ } else if (id_surface == hmi_setting->home.id) {
+ *is_home_on = !(*is_home_on);
+ if (*is_home_on) {
+ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_ON);
+ } else {
+ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);
+ }
+ }
+}
+
+/**
+ * Even handler of Pointer event. IVI system is usually manipulated by touch
+ * screen. However, some systems also have pointer device.
+ * Release is the same behavior as touch off
+ * Pressed is the same behavior as touch on
+ */
+static void
+PointerHandleButton(void* data, struct wl_pointer* wlPointer, uint32_t serial,
+ uint32_t time, uint32_t button, uint32_t state)
+{
+ (void)wlPointer;
+ (void)serial;
+ (void)time;
+ struct wlContextCommon *pCtx = data;
+ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
+
+ if (BTN_RIGHT == button) {
+ return;
+ }
+
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
+
+ switch (state) {
+ case WL_POINTER_BUTTON_STATE_RELEASED:
+ touch_up(hmi_ctrl, id_surface, &pCtx->is_home_on, pCtx->hmi_setting);
+ break;
+
+ case WL_POINTER_BUTTON_STATE_PRESSED:
+
+ if (isWorkspaceSurface(id_surface, pCtx->hmi_setting)) {
+ ivi_hmi_controller_workspace_control(hmi_ctrl, pCtx->wlSeat, serial);
+ }
+
+ break;
+ }
+#ifdef _DEBUG
+ printf("ENTER PointerHandleButton: button(%d), state(%d)\n", button, state);
+#endif
+}
+
+static void
+PointerHandleAxis(void* data, struct wl_pointer* wlPointer, uint32_t time,
+ uint32_t axis, wl_fixed_t value)
+{
+ (void)data;
+ (void)wlPointer;
+ (void)time;
+#ifdef _DEBUG
+ printf("ENTER PointerHandleAxis: axis(%d), value(%d)\n", axis, value);
+#endif
+}
+
+static struct wl_pointer_listener pointer_listener = {
+ PointerHandleEnter,
+ PointerHandleLeave,
+ PointerHandleMotion,
+ PointerHandleButton,
+ PointerHandleAxis
+};
+
+/**
+ * Even handler of touch event
+ */
+static void
+TouchHandleDown(void *data, struct wl_touch *wlTouch, uint32_t serial, uint32_t time,
+ struct wl_surface *surface, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
+{
+ struct wlContextCommon *pCtx = data;
+ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
+
+ if (0 == id){
+ pCtx->enterSurface = surface;
+ }
+
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
+
+ /**
+ * When touch down happens on surfaces of workspace, ask hmi-controller to start
+ * control workspace to select page of workspace.
+ * After sending seat to hmi-controller by ivi_hmi_controller_workspace_control,
+ * hmi-controller-homescreen doesn't receive any event till hmi-controller sends
+ * back it.
+ */
+ if (isWorkspaceSurface(id_surface, pCtx->hmi_setting)) {
+ ivi_hmi_controller_workspace_control(hmi_ctrl, pCtx->wlSeat, serial);
+ }
+}
+
+static void
+TouchHandleUp(void *data, struct wl_touch *wlTouch, uint32_t serial, uint32_t time,
+ int32_t id)
+{
+ (void)serial;
+ (void)time;
+ struct wlContextCommon *pCtx = data;
+ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
+
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
+
+ /**
+ * triggering event according to touch-up happening on which surface.
+ */
+ if (id == 0){
+ touch_up(hmi_ctrl, id_surface, &pCtx->is_home_on, pCtx->hmi_setting);
+ }
+}
+
+static void
+TouchHandleMotion(void *data, struct wl_touch *wlTouch, uint32_t time,
+ int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
+{
+}
+
+static void
+TouchHandleFrame(void *data, struct wl_touch *wlTouch)
+{
+}
+
+static void
+TouchHandleCancel(void *data, struct wl_touch *wlTouch)
+{
+}
+
+static struct wl_touch_listener touch_listener = {
+ TouchHandleDown,
+ TouchHandleUp,
+ TouchHandleMotion,
+ TouchHandleFrame,
+ TouchHandleCancel,
+};
+
+/**
+ * Handler of capabilities
+ */
+static void
+seat_handle_capabilities(void* data, struct wl_seat* seat, uint32_t caps)
+{
+ (void)seat;
+ struct wlContextCommon* p_wlCtx = (struct wlContextCommon*)data;
+ struct wl_seat* wlSeat = p_wlCtx->wlSeat;
+ struct wl_pointer* wlPointer = p_wlCtx->wlPointer;
+ struct wl_touch* wlTouch = p_wlCtx->wlTouch;
+
+ if (p_wlCtx->hmi_setting->cursor_theme) {
+ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlPointer){
+ wlPointer = wl_seat_get_pointer(wlSeat);
+ wl_pointer_set_user_data(wlPointer, data);
+ wl_pointer_add_listener(wlPointer, &pointer_listener, data);
+ } else
+ if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlPointer){
+ wl_pointer_destroy(wlPointer);
+ wlPointer = NULL;
+ }
+ p_wlCtx->wlPointer = wlPointer;
+ }
+
+ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wlTouch){
+ wlTouch = wl_seat_get_touch(wlSeat);
+ wl_touch_set_user_data(wlTouch, data);
+ wl_touch_add_listener(wlTouch, &touch_listener, data);
+ } else
+ if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wlTouch){
+ wl_touch_destroy(wlTouch);
+ wlTouch = NULL;
+ }
+ p_wlCtx->wlTouch = wlTouch;
+}
+
+static struct wl_seat_listener seat_Listener = {
+ seat_handle_capabilities,
+};
+
+/**
+ * Registration of event
+ * This event is received when hmi-controller server finished controlling
+ * workspace.
+ */
+static void
+ivi_hmi_controller_workspace_end_control(void *data,
+ struct ivi_hmi_controller *hmi_ctrl,
+ int32_t is_controlled)
+{
+ if (is_controlled) {
+ return;
+ }
+
+ struct wlContextCommon *pCtx = data;
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
+
+ /**
+ * During being controlled by hmi-controller, any input event is not
+ * notified. So when control ends with touch up, it invokes launcher
+ * if up event happens on a launcher surface.
+ *
+ */
+ if (launcher_button(id_surface, &pCtx->hmi_setting->launcher_list)) {
+ pCtx->is_home_on = 0;
+ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);
+ }
+}
+
+static const struct ivi_hmi_controller_listener hmi_controller_listener = {
+ ivi_hmi_controller_workspace_end_control
+};
+
+/**
+ * Registration of interfaces
+ */
+static void
+registry_handle_global(void* data, struct wl_registry* registry, uint32_t name,
+ const char *interface, uint32_t version)
+{
+ (void)version;
+ struct wlContextCommon* p_wlCtx = (struct wlContextCommon*)data;
+
+ do {
+ if (!strcmp(interface, "wl_compositor")) {
+ p_wlCtx->wlCompositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
+ break;
+ }
+ if (!strcmp(interface, "wl_shm")) {
+ p_wlCtx->wlShm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
+ wl_shm_add_listener(p_wlCtx->wlShm, &shm_listenter, p_wlCtx);
+ break;
+ }
+ if (!strcmp(interface, "wl_seat")) {
+ p_wlCtx->wlSeat = wl_registry_bind(registry, name, &wl_seat_interface, 1);
+ wl_seat_add_listener(p_wlCtx->wlSeat, &seat_Listener, data);
+ break;
+ }
+ if (!strcmp(interface, "ivi_application")) {
+ p_wlCtx->iviApplication = wl_registry_bind(registry, name, &ivi_application_interface, 1);
+ break;
+ }
+ if (!strcmp(interface, "ivi_hmi_controller")) {
+ p_wlCtx->hmiCtrl = wl_registry_bind(registry, name, &ivi_hmi_controller_interface, 1);
+
+ if (p_wlCtx->hmiCtrl) {
+ ivi_hmi_controller_add_listener(p_wlCtx->hmiCtrl, &hmi_controller_listener, p_wlCtx);
+ }
+ break;
+ }
+
+ } while(0);
+}
+
+static const struct wl_registry_listener registry_listener = {
+ registry_handle_global,
+ NULL
+};
+
+static void
+frame_listener_func(void *data, struct wl_callback *callback, uint32_t time)
+{
+ if (callback) {
+ wl_callback_destroy(callback);
+ }
+}
+
+static const struct wl_callback_listener frame_listener = {
+ frame_listener_func
+};
+
+/*
+ * The following correspondences between file names and cursors was copied
+ * from: https://bugs.kde.org/attachment.cgi?id=67313
+ */
+static const char *bottom_left_corners[] = {
+ "bottom_left_corner",
+ "sw-resize",
+ "size_bdiag"
+};
+
+static const char *bottom_right_corners[] = {
+ "bottom_right_corner",
+ "se-resize",
+ "size_fdiag"
+};
+
+static const char *bottom_sides[] = {
+ "bottom_side",
+ "s-resize",
+ "size_ver"
+};
+
+static const char *grabbings[] = {
+ "grabbing",
+ "closedhand",
+ "208530c400c041818281048008011002"
+};
+
+static const char *left_ptrs[] = {
+ "left_ptr",
+ "default",
+ "top_left_arrow",
+ "left-arrow"
+};
+
+static const char *left_sides[] = {
+ "left_side",
+ "w-resize",
+ "size_hor"
+};
+
+static const char *right_sides[] = {
+ "right_side",
+ "e-resize",
+ "size_hor"
+};
+
+static const char *top_left_corners[] = {
+ "top_left_corner",
+ "nw-resize",
+ "size_fdiag"
+};
+
+static const char *top_right_corners[] = {
+ "top_right_corner",
+ "ne-resize",
+ "size_bdiag"
+};
+
+static const char *top_sides[] = {
+ "top_side",
+ "n-resize",
+ "size_ver"
+};
+
+static const char *xterms[] = {
+ "xterm",
+ "ibeam",
+ "text"
+};
+
+static const char *hand1s[] = {
+ "hand1",
+ "pointer",
+ "pointing_hand",
+ "e29285e634086352946a0e7090d73106"
+};
+
+static const char *watches[] = {
+ "watch",
+ "wait",
+ "0426c94ea35c87780ff01dc239897213"
+};
+
+struct cursor_alternatives {
+ const char **names;
+ size_t count;
+};
+
+static const struct cursor_alternatives cursors[] = {
+ {bottom_left_corners, ARRAY_LENGTH(bottom_left_corners)},
+ {bottom_right_corners, ARRAY_LENGTH(bottom_right_corners)},
+ {bottom_sides, ARRAY_LENGTH(bottom_sides)},
+ {grabbings, ARRAY_LENGTH(grabbings)},
+ {left_ptrs, ARRAY_LENGTH(left_ptrs)},
+ {left_sides, ARRAY_LENGTH(left_sides)},
+ {right_sides, ARRAY_LENGTH(right_sides)},
+ {top_left_corners, ARRAY_LENGTH(top_left_corners)},
+ {top_right_corners, ARRAY_LENGTH(top_right_corners)},
+ {top_sides, ARRAY_LENGTH(top_sides)},
+ {xterms, ARRAY_LENGTH(xterms)},
+ {hand1s, ARRAY_LENGTH(hand1s)},
+ {watches, ARRAY_LENGTH(watches)},
+};
+
+static void
+create_cursors(struct wlContextCommon *cmm)
+{
+ uint32_t i = 0;
+ uint32_t j = 0;
+ struct wl_cursor *cursor = NULL;
+ char* cursor_theme = cmm->hmi_setting->cursor_theme;
+ int32_t cursor_size = cmm->hmi_setting->cursor_size;
+
+ cmm->cursor_theme = wl_cursor_theme_load(cursor_theme, cursor_size, cmm->wlShm);
+
+ cmm->cursors = MEM_ALLOC(ARRAY_LENGTH(cursors) * sizeof(cmm->cursors[0]));
+
+ for (i = 0; i < ARRAY_LENGTH(cursors); i++) {
+ cursor = NULL;
+
+ for (j = 0; !cursor && j < cursors[i].count; ++j) {
+ cursor = wl_cursor_theme_get_cursor(
+ cmm->cursor_theme, cursors[i].names[j]);
+ }
+
+ if (!cursor) {
+ fprintf(stderr, "could not load cursor '%s'\n",
+ cursors[i].names[0]);
+ }
+
+ cmm->cursors[i] = cursor;
+ }
+}
+
+static void
+destroy_cursors(struct wlContextCommon *cmm)
+{
+ if (cmm->cursor_theme) {
+ wl_cursor_theme_destroy(cmm->cursor_theme);
+ }
+
+ free(cmm->cursors);
+}
+
+/**
+ * Internal method to prepare parts of UI
+ */
+static void
+createShmBuffer(struct wlContextStruct *p_wlCtx)
+{
+ struct wl_shm_pool *pool;
+
+ char filename[] = "/tmp/wayland-shm-XXXXXX";
+ int fd = -1;
+ int size = 0;
+ int width = 0;
+ int height = 0;
+ int stride = 0;
+
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ fprintf(stderr, "open %s failed: %m\n", filename);
+ return;
+ }
+
+ width = cairo_image_surface_get_width(p_wlCtx->ctx_image);
+ height = cairo_image_surface_get_height(p_wlCtx->ctx_image);
+ stride = cairo_image_surface_get_stride(p_wlCtx->ctx_image);
+
+ size = stride * height;
+ if (ftruncate(fd, size) < 0) {
+ fprintf(stderr, "ftruncate failed: %m\n");
+ close(fd);
+ return;
+ }
+
+ p_wlCtx->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+ if (MAP_FAILED == p_wlCtx->data) {
+ fprintf(stderr, "mmap failed: %m\n");
+ close(fd);
+ return;
+ }
+
+ pool = wl_shm_create_pool(p_wlCtx->cmm.wlShm, fd, size);
+ p_wlCtx->wlBuffer = wl_shm_pool_create_buffer(pool, 0,
+ width,
+ height,
+ stride,
+ WL_SHM_FORMAT_ARGB8888);
+
+ if (NULL == p_wlCtx->wlBuffer) {
+ fprintf(stderr, "wl_shm_create_buffer failed: %m\n");
+ close(fd);
+ return;
+ }
+ wl_shm_pool_destroy(pool);
+ close(fd);
+
+ return;
+}
+
+static void
+destroyWLContextCommon(struct wlContextCommon *p_wlCtx)
+{
+ destroy_cursors(p_wlCtx);
+
+ if (p_wlCtx->pointer_surface) {
+ wl_surface_destroy(p_wlCtx->pointer_surface);
+ }
+
+ if (p_wlCtx->wlCompositor) {
+ wl_compositor_destroy(p_wlCtx->wlCompositor);
+ }
+}
+
+static void
+destroyWLContextStruct(struct wlContextStruct *p_wlCtx)
+{
+ if (p_wlCtx->wlSurface) {
+ wl_surface_destroy(p_wlCtx->wlSurface);
+ }
+
+ if (p_wlCtx->ctx_image) {
+ cairo_surface_destroy(p_wlCtx->ctx_image);
+ p_wlCtx->ctx_image = NULL;
+ }
+}
+
+static int
+createWLContext(struct wlContextStruct *p_wlCtx)
+{
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);
+
+ p_wlCtx->wlSurface = wl_compositor_create_surface(p_wlCtx->cmm.wlCompositor);
+ if (NULL == p_wlCtx->wlSurface) {
+ printf("Error: wl_compositor_create_surface failed.\n");
+ destroyWLContextCommon(&p_wlCtx->cmm);
+ abort();
+ }
+
+
+ createShmBuffer(p_wlCtx);
+
+ wl_display_flush(p_wlCtx->cmm.wlDisplay);
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);
+
+ return 0;
+}
+
+static void
+drawImage(struct wlContextStruct *p_wlCtx)
+{
+ struct wl_callback *callback;
+
+ int width = 0;
+ int height = 0;
+ int stride = 0;
+ void *data = NULL;
+
+ width = cairo_image_surface_get_width(p_wlCtx->ctx_image);
+ height = cairo_image_surface_get_height(p_wlCtx->ctx_image);
+ stride = cairo_image_surface_get_stride(p_wlCtx->ctx_image);
+ data = cairo_image_surface_get_data(p_wlCtx->ctx_image);
+
+ memcpy(p_wlCtx->data, data, stride * height);
+
+ wl_surface_attach(p_wlCtx->wlSurface, p_wlCtx->wlBuffer, 0, 0);
+ wl_surface_damage(p_wlCtx->wlSurface, 0, 0, width, height);
+
+ callback = wl_surface_frame(p_wlCtx->wlSurface);
+ wl_callback_add_listener(callback, &frame_listener, NULL);
+
+ wl_surface_commit(p_wlCtx->wlSurface);
+
+ wl_display_flush(p_wlCtx->cmm.wlDisplay);
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);
+}
+
+static void
+create_ivisurface(struct wlContextStruct *p_wlCtx,
+ uint32_t id_surface,
+ cairo_surface_t* surface)
+{
+ struct ivi_surface *ivisurf = NULL;
+
+ p_wlCtx->ctx_image = surface;
+
+ p_wlCtx->id_surface = id_surface;
+ wl_list_init(&p_wlCtx->link);
+ wl_list_insert(p_wlCtx->cmm.list_wlContextStruct, &p_wlCtx->link);
+
+ createWLContext(p_wlCtx);
+
+ ivisurf = ivi_application_surface_create(p_wlCtx->cmm.iviApplication,
+ id_surface, p_wlCtx->wlSurface);
+ if (ivisurf == NULL) {
+ fprintf(stderr, "Failed to create ivi_client_surface\n");
+ return;
+ }
+
+ drawImage(p_wlCtx);
+
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);
+}
+
+static void
+create_ivisurfaceFromFile(struct wlContextStruct *p_wlCtx,
+ uint32_t id_surface,
+ const char* imageFile)
+{
+ cairo_surface_t* surface = load_cairo_surface(imageFile);
+
+ if (NULL == surface) {
+ fprintf(stderr, "Failed to load_cairo_surface %s\n", imageFile);
+ return;
+ }
+
+ create_ivisurface(p_wlCtx, id_surface, surface);
+}
+
+static void
+set_hex_color(cairo_t *cr, uint32_t color)
+{
+ cairo_set_source_rgba(cr,
+ ((color >> 16) & 0xff) / 255.0,
+ ((color >> 8) & 0xff) / 255.0,
+ ((color >> 0) & 0xff) / 255.0,
+ ((color >> 24) & 0xff) / 255.0);
+}
+
+static void
+create_ivisurfaceFromColor(struct wlContextStruct *p_wlCtx,
+ uint32_t id_surface,
+ uint32_t width, uint32_t height,
+ uint32_t color)
+{
+ cairo_surface_t *surface = NULL;
+ cairo_t *cr = NULL;
+
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+
+ cr = cairo_create(surface);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_rectangle(cr, 0, 0, width, height);
+ set_hex_color(cr, color);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+
+ create_ivisurface(p_wlCtx, id_surface, surface);
+}
+
+/**
+ * Internal method to set up UI by using ivi-hmi-controller
+ */
+static void
+create_background(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
+ const char* imageFile)
+{
+ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
+ ivi_hmi_controller_set_background(p_wlCtx->cmm.hmiCtrl, id_surface);
+}
+
+static void
+create_panel(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
+ const char* imageFile)
+{
+ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
+ ivi_hmi_controller_set_panel(p_wlCtx->cmm.hmiCtrl, id_surface);
+}
+
+static void
+create_button(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
+ const char* imageFile, uint32_t number)
+{
+ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
+ ivi_hmi_controller_set_button(p_wlCtx->cmm.hmiCtrl, id_surface, number);
+}
+
+static void
+create_home_button(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
+ const char* imageFile)
+{
+ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
+ ivi_hmi_controller_set_home_button(p_wlCtx->cmm.hmiCtrl, id_surface);
+}
+
+static void
+create_workspace_background(
+ struct wlContextStruct *p_wlCtx, struct hmi_homescreen_srf *srf)
+{
+ create_ivisurfaceFromColor(p_wlCtx, srf->id, 1, 1, srf->color);
+ ivi_hmi_controller_set_workspacebackground(p_wlCtx->cmm.hmiCtrl, srf->id);
+}
+
+static int compare_launcher(const void* data1, const void* data2)
+{
+ struct hmi_homescreen_launcher *launcher1 = *(struct hmi_homescreen_launcher**)data1;
+ struct hmi_homescreen_launcher *launcher2 = *(struct hmi_homescreen_launcher**)data2;
+ return launcher1->workspace_id - launcher2->workspace_id;
+}
+
+static void
+create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
+{
+ int launcher_count = wl_list_length(launcher_list);
+
+ if (0 == launcher_count) {
+ return;
+ }
+
+ struct hmi_homescreen_launcher** launchers;
+ launchers = MEM_ALLOC(launcher_count * sizeof(*launchers));
+
+ int ii = 0;
+ struct hmi_homescreen_launcher *launcher = NULL;
+
+ wl_list_for_each(launcher, launcher_list, link) {
+ launchers[ii] = launcher;
+ ii++;
+ }
+
+ qsort(launchers, launcher_count, sizeof(*launchers), compare_launcher);
+
+ int start = 0;
+
+ for (ii = 0; ii < launcher_count; ii++) {
+
+ if (ii != launcher_count -1 &&
+ launchers[ii]->workspace_id == launchers[ii + 1]->workspace_id) {
+ continue;
+ }
+
+ struct wl_array surface_ids;
+ wl_array_init(&surface_ids);
+
+ int jj = 0;
+ for (jj = start; jj <= ii; jj++) {
+ uint32_t *id = wl_array_add(&surface_ids, sizeof(*id));
+ *id = launchers[jj]->icon_surface_id;
+
+ struct wlContextStruct *p_wlCtx = MEM_ALLOC(sizeof(*p_wlCtx));
+ p_wlCtx->cmm = *cmm;
+
+ create_ivisurfaceFromFile(p_wlCtx, *id, launchers[jj]->icon);
+ }
+
+ ivi_hmi_controller_add_launchers(cmm->hmiCtrl, &surface_ids, 256);
+ wl_array_release(&surface_ids);
+ start = ii + 1;
+ }
+
+ free(launchers);
+}
+
+static void sigFunc(int signum)
+{
+ gRun = 0;
+}
+
+/**
+ * Internal method to read out weston.ini to get configuration
+ */
+static struct hmi_homescreen_setting*
+hmi_homescreen_setting_create(void)
+{
+ struct hmi_homescreen_setting* setting = MEM_ALLOC(sizeof(*setting));
+
+ wl_list_init(&setting->workspace_list);
+ wl_list_init(&setting->launcher_list);
+
+ struct weston_config *config = NULL;
+ config = weston_config_parse("weston.ini");
+
+ struct weston_config_section *shellSection = NULL;
+ shellSection = weston_config_get_section(config, "ivi-shell", NULL, NULL);
+
+ weston_config_section_get_string(
+ shellSection, "cursor-theme", &setting->cursor_theme, NULL);
+
+ weston_config_section_get_int(shellSection, "cursor-size", &setting->cursor_size, 32);
+
+ uint32_t workspace_layer_id;
+ weston_config_section_get_uint(
+ shellSection, "workspace-layer-id", &workspace_layer_id, 3000);
+
+ weston_config_section_get_string(
+ shellSection, "background-image", &setting->background.filePath,
+ DATADIR "/weston/background.png");
+
+ weston_config_section_get_uint(
+ shellSection, "background-id", &setting->background.id, 1001);
+
+ weston_config_section_get_string(
+ shellSection, "panel-image", &setting->panel.filePath,
+ DATADIR "/weston/panel.png");
+
+ weston_config_section_get_uint(
+ shellSection, "panel-id", &setting->panel.id, 1002);
+
+ weston_config_section_get_string(
+ shellSection, "tiling-image", &setting->tiling.filePath,
+ DATADIR "/weston/tiling.png");
+
+ weston_config_section_get_uint(
+ shellSection, "tiling-id", &setting->tiling.id, 1003);
+
+ weston_config_section_get_string(
+ shellSection, "sidebyside-image", &setting->sidebyside.filePath,
+ DATADIR "/weston/sidebyside.png");
+
+ weston_config_section_get_uint(
+ shellSection, "sidebyside-id", &setting->sidebyside.id, 1004);
+
+ weston_config_section_get_string(
+ shellSection, "fullscreen-image", &setting->fullscreen.filePath,
+ DATADIR "/weston/fullscreen.png");
+
+ weston_config_section_get_uint(
+ shellSection, "fullscreen-id", &setting->fullscreen.id, 1005);
+
+ weston_config_section_get_string(
+ shellSection, "random-image", &setting->random.filePath,
+ DATADIR "/weston/random.png");
+
+ weston_config_section_get_uint(
+ shellSection, "random-id", &setting->random.id, 1006);
+
+ weston_config_section_get_string(
+ shellSection, "home-image", &setting->home.filePath,
+ DATADIR "/weston/home.png");
+
+ weston_config_section_get_uint(
+ shellSection, "home-id", &setting->home.id, 1007);
+
+ weston_config_section_get_uint(
+ shellSection, "workspace-background-color",
+ &setting->workspace_background.color, 0x99000000);
+
+ weston_config_section_get_uint(
+ shellSection, "workspace-background-id",
+ &setting->workspace_background.id, 2001);
+
+ struct weston_config_section *section = NULL;
+ const char *name = NULL;
+
+ uint32_t icon_surface_id = workspace_layer_id + 1;
+
+ while (weston_config_next_section(config, &section, &name)) {
+
+ if (0 == strcmp(name, "ivi-launcher")) {
+
+ struct hmi_homescreen_launcher *launcher = NULL;
+ launcher = MEM_ALLOC(sizeof(*launcher));
+ wl_list_init(&launcher->link);
+ launcher->icon_surface_id = icon_surface_id;
+ icon_surface_id++;
+
+ weston_config_section_get_string(section, "icon", &launcher->icon, NULL);
+ weston_config_section_get_string(section, "path", &launcher->path, NULL);
+ weston_config_section_get_uint(section, "workspace-id", &launcher->workspace_id, 0);
+
+ wl_list_insert(setting->launcher_list.prev, &launcher->link);
+ }
+ }
+
+ weston_config_destroy(config);
+ return setting;
+}
+
+/**
+ * Main thread
+ *
+ * The basic flow are as followed,
+ * 1/ read configuration from weston.ini by hmi_homescreen_setting_create
+ * 2/ draw png file to surface according to configuration of weston.ini and
+ * set up UI by using ivi-hmi-controller protocol by each create_* method
+ */
+static void*
+client_thread(void *p_ret)
+{
+ struct wlContextCommon wlCtxCommon;
+ struct wlContextStruct wlCtx_BackGround;
+ struct wlContextStruct wlCtx_Panel;
+ struct wlContextStruct wlCtx_Button_1;
+ struct wlContextStruct wlCtx_Button_2;
+ struct wlContextStruct wlCtx_Button_3;
+ struct wlContextStruct wlCtx_Button_4;
+ struct wlContextStruct wlCtx_HomeButton;
+ struct wlContextStruct wlCtx_WorkSpaceBackGround;
+ struct wl_list launcher_wlCtxList;
+
+ memset(&wlCtxCommon, 0x00, sizeof(wlCtxCommon));
+ memset(&wlCtx_BackGround, 0x00, sizeof(wlCtx_BackGround));
+ memset(&wlCtx_Panel, 0x00, sizeof(wlCtx_Panel));
+ memset(&wlCtx_Button_1, 0x00, sizeof(wlCtx_Button_1));
+ memset(&wlCtx_Button_2, 0x00, sizeof(wlCtx_Button_2));
+ memset(&wlCtx_Button_3, 0x00, sizeof(wlCtx_Button_3));
+ memset(&wlCtx_Button_4, 0x00, sizeof(wlCtx_Button_4));
+ memset(&wlCtx_HomeButton, 0x00, sizeof(wlCtx_HomeButton));
+ memset(&wlCtx_WorkSpaceBackGround, 0x00, sizeof(wlCtx_WorkSpaceBackGround));
+ wl_list_init(&launcher_wlCtxList);
+ wlCtxCommon.list_wlContextStruct = MEM_ALLOC(sizeof(struct wl_list));
+ assert(wlCtxCommon.list_wlContextStruct);
+ wl_list_init(wlCtxCommon.list_wlContextStruct);
+
+ struct hmi_homescreen_setting *hmi_setting = hmi_homescreen_setting_create();
+ wlCtxCommon.hmi_setting = hmi_setting;
+
+ gRun = 1;
+
+ wlCtxCommon.wlDisplay = wl_display_connect(NULL);
+ if (NULL == wlCtxCommon.wlDisplay) {
+ printf("Error: wl_display_connect failed.\n");
+ return NULL;
+ }
+
+ /* get wl_registry */
+ wlCtxCommon.wlRegistry = wl_display_get_registry(wlCtxCommon.wlDisplay);
+ wl_registry_add_listener(wlCtxCommon.wlRegistry,
+ &registry_listener, &wlCtxCommon);
+ wl_display_dispatch(wlCtxCommon.wlDisplay);
+ wl_display_roundtrip(wlCtxCommon.wlDisplay);
+
+ if (wlCtxCommon.hmi_setting->cursor_theme) {
+ create_cursors(&wlCtxCommon);
+
+ wlCtxCommon.pointer_surface =
+ wl_compositor_create_surface(wlCtxCommon.wlCompositor);
+
+ wlCtxCommon.current_cursor = CURSOR_LEFT_PTR;
+ }
+
+ wlCtx_BackGround.cmm = wlCtxCommon;
+ wlCtx_Panel.cmm = wlCtxCommon;
+ wlCtx_Button_1.cmm = wlCtxCommon;
+ wlCtx_Button_2.cmm = wlCtxCommon;
+ wlCtx_Button_3.cmm = wlCtxCommon;
+ wlCtx_Button_4.cmm = wlCtxCommon;
+ wlCtx_HomeButton.cmm = wlCtxCommon;
+ wlCtx_WorkSpaceBackGround.cmm = wlCtxCommon;
+
+ /* create desktop widgets */
+ create_background(&wlCtx_BackGround, hmi_setting->background.id,
+ hmi_setting->background.filePath);
+
+ create_panel(&wlCtx_Panel, hmi_setting->panel.id,
+ hmi_setting->panel.filePath);
+
+ create_button(&wlCtx_Button_1, hmi_setting->tiling.id,
+ hmi_setting->tiling.filePath, 0);
+
+ create_button(&wlCtx_Button_2, hmi_setting->sidebyside.id,
+ hmi_setting->sidebyside.filePath, 1);
+
+ create_button(&wlCtx_Button_3, hmi_setting->fullscreen.id,
+ hmi_setting->fullscreen.filePath, 2);
+
+ create_button(&wlCtx_Button_4, hmi_setting->random.id,
+ hmi_setting->random.filePath, 3);
+
+ create_workspace_background(&wlCtx_WorkSpaceBackGround,
+ &hmi_setting->workspace_background);
+
+ create_launchers(&wlCtxCommon, &hmi_setting->launcher_list);
+
+ create_home_button(&wlCtx_HomeButton, hmi_setting->home.id,
+ hmi_setting->home.filePath);
+ /* signal handling */
+ signal(SIGINT, sigFunc);
+ signal(SIGKILL, sigFunc);
+
+ while(gRun) {
+ wl_display_roundtrip(wlCtxCommon.wlDisplay);
+ usleep(5000);
+ }
+
+ struct wlContextStruct* pWlCtxSt = NULL;
+ wl_list_for_each(pWlCtxSt, wlCtxCommon.list_wlContextStruct, link) {
+ destroyWLContextStruct(pWlCtxSt);
+ }
+
+ destroyWLContextCommon(&wlCtxCommon);
+ free(wlCtxCommon.list_wlContextStruct);
+
+ return NULL;
+}
+
+/*****************************************************************************
+ * exported functions
+ ****************************************************************************/
+int
+hmi_client_start(void)
+{
+ pthread_attr_t thread_attrs;
+ uint32_t ret = 0;
+ pthread_t thread;
+
+ pthread_attr_init(&thread_attrs);
+ pthread_attr_setdetachstate(&thread_attrs, PTHREAD_CREATE_JOINABLE);
+ ret = pthread_create(&thread, &thread_attrs, client_thread, NULL);
+ if (ret != 0) {
+ fprintf(stderr, "Failed to start internal receive \
+ thread. returned %d\n", ret);
+ }
+
+ return 0;
+}
diff --git a/ivi-shell/hmi-controller-homescreen.h b/ivi-shell/hmi-controller-homescreen.h
new file mode 100644
index 0000000..31416de
--- /dev/null
+++ b/ivi-shell/hmi-controller-homescreen.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HMI_CONTROLLER_HOMESCREEN_H_
+#define _HMI_CONTROLLER_HOMESCREEN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int hmi_client_start(void);
+
+#ifdef __cplusplus
+} /**/
+#endif /* __cplusplus */
+
+#endif /* _HMI_CONTROLLER_HOMESCREEN_H_ */
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:03:53 UTC
Permalink
to build references;ivi-hmi-controller protocol, hmi-controller,
and hmi-controller-homescreen.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
ivi-shell/.gitignore | 7 +++++++
ivi-shell/Makefile.am | 21 +++++++++++++++++++--
2 files changed, 26 insertions(+), 2 deletions(-)
create mode 100644 ivi-shell/.gitignore

diff --git a/ivi-shell/.gitignore b/ivi-shell/.gitignore
new file mode 100644
index 0000000..9f31bfd
--- /dev/null
+++ b/ivi-shell/.gitignore
@@ -0,0 +1,7 @@
+ivi-application-client-protocol.h
+ivi-application-protocol.c
+ivi-application-server-protocol.h
+ivi-hmi-controller-client-protocol.h
+ivi-hmi-controller-protocol.c
+ivi-hmi-controller-server-protocol.h
+weston.ini
diff --git a/ivi-shell/Makefile.am b/ivi-shell/Makefile.am
index d0c0d62..afaa5e3 100644
--- a/ivi-shell/Makefile.am
+++ b/ivi-shell/Makefile.am
@@ -2,7 +2,8 @@ moduledir = $(libdir)/weston

module_LTLIBRARIES = \
$(libweston_layout) \
- $(ivi_shell)
+ $(ivi_shell) \
+ $(hmi_controller)

AM_CPPFLAGS = \
-I$(top_srcdir)/shared \
@@ -39,12 +40,28 @@ ivi_shell_la_SOURCES = \
ivi-application-protocol.c \
ivi-application-server-protocol.h

+hmi_controller = hmi-controller.la
+hmi_controller_la_LDFLAGS = -module -avoid-version
+hmi_controller_la_LIBADD = $(CLIENT_LIBS) $(IVI_SHELL_LIBS) ./libweston-layout.la ../shared/libshared-cairo.la
+hmi_controller_la_CFLAGS = $(GCC_CFLAGS) $(IVI_SHELL_CFLAGS)
+hmi_controller_la_SOURCES = \
+ hmi-controller.c \
+ hmi-controller-homescreen.h \
+ hmi-controller-homescreen.c \
+ ivi-application-protocol.c \
+ ivi-application-client-protocol.h \
+ ivi-hmi-controller-protocol.c \
+ ivi-hmi-controller-client-protocol.h \
+ ivi-hmi-controller-server-protocol.h
endif

BUILT_SOURCES = \
ivi-application-protocol.c \
ivi-application-server-protocol.h \
- ivi-application-client-protocol.h
+ ivi-application-client-protocol.h \
+ ivi-hmi-controller-protocol.c \
+ ivi-hmi-controller-client-protocol.h \
+ ivi-hmi-controller-server-protocol.h

CLEANFILES = $(BUILT_SOURCES)

--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:05:35 UTC
Permalink
Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
data/Makefile.am | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/data/Makefile.am b/data/Makefile.am
index a7cc944..2aa6e5c 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -9,7 +9,19 @@ dist_westondata_DATA = \
icon_window.png \
sign_close.png \
sign_maximize.png \
- sign_minimize.png
+ sign_minimize.png \
+ background.png \
+ tiling.png \
+ fullscreen.png \
+ panel.png \
+ random.png \
+ sidebyside.png \
+ home.png \
+ icon_ivi_clickdot.png \
+ icon_ivi_flower.png \
+ icon_ivi_simple-egl.png \
+ icon_ivi_simple-shm.png \
+ icon_ivi_smoke.png

if HAVE_RSVG_CONVERT
wayland_icon_png = wayland.png
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:06:13 UTC
Permalink
Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
ivi-shell/Makefile.am | 12 ++++++++
ivi-shell/weston.ini.in | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 91 insertions(+)
create mode 100644 ivi-shell/weston.ini.in

diff --git a/ivi-shell/Makefile.am b/ivi-shell/Makefile.am
index afaa5e3..333abb7 100644
--- a/ivi-shell/Makefile.am
+++ b/ivi-shell/Makefile.am
@@ -67,3 +67,15 @@ CLEANFILES = $(BUILT_SOURCES)

wayland_protocoldir = $(top_srcdir)/protocol
include $(top_srcdir)/wayland-scanner.mk
+
+
+weston.ini : $(srcdir)/weston.ini.in
+ $(AM_V_GEN)$(SED) \
+ -e 's|@bindir[@]|$(bindir)|g' \
+ -e 's|@abs_top_builddir[@]|$(abs_top_builddir)|g' \
+ -e 's|@libexecdir[@]|$(libexecdir)|g' \
+ $< > $@
+
+all-local : weston.ini
+
+CLEANFILES += weston.ini
diff --git a/ivi-shell/weston.ini.in b/ivi-shell/weston.ini.in
new file mode 100644
index 0000000..c9a6861
--- /dev/null
+++ b/ivi-shell/weston.ini.in
@@ -0,0 +1,79 @@
+[core]
+shell=ivi-shell.so
+modules=hmi-controller.so
+
+[ivi-shell]
+cursor-theme=default
+cursor-size=32
+
+base-layer-id=1000
+workspace-background-layer-id=2000
+workspace-layer-id=3000
+application-layer-id=4000
+
+background-image=@abs_top_builddir@/data/background.png
+background-id=1001
+panel-image=@abs_top_builddir@/data/panel.png
+panel-id=1002
+tiling-image=@abs_top_builddir@/data/tiling.png
+tiling-id=1003
+sidebyside-image=@abs_top_builddir@/data/sidebyside.png
+sidebyside-id=1004
+fullscreen-image=@abs_top_builddir@/data/fullscreen.png
+fullscreen-id=1005
+random-image=@abs_top_builddir@/data/random.png
+random-id=1006
+home-image=@abs_top_builddir@/data/home.png
+home-id=1007
+workspace-background-color=0x99000000
+workspace-background-id=2001
+
+[ivi-launcher]
+workspace-id=0
+icon=@abs_top_builddir@/data/icon_ivi_flower.png
+path=@abs_top_builddir@/clients/weston-flower-ivi
+
+[ivi-launcher]
+workspace-id=0
+icon=@abs_top_builddir@/data/icon_ivi_clickdot.png
+path=@abs_top_builddir@/clients/weston-clickdot-ivi
+
+[ivi-launcher]
+workspace-id=1
+icon=@abs_top_builddir@/data/icon_ivi_simple-egl.png
+path=@abs_top_builddir@/clients/weston-simple-egl-ivi
+
+[ivi-launcher]
+workspace-id=1
+icon=@abs_top_builddir@/data/icon_ivi_simple-shm.png
+path=@abs_top_builddir@/clients/weston-simple-shm-ivi
+
+[ivi-launcher]
+workspace-id=2
+icon=@abs_top_builddir@/data/icon_ivi_smoke.png
+path=@abs_top_builddir@/clients/weston-smoke-ivi
+
+[ivi-launcher]
+workspace-id=3
+icon=@abs_top_builddir@/data/icon_ivi_flower.png
+path=@abs_top_builddir@/clients/weston-flower-ivi
+
+[ivi-launcher]
+workspace-id=3
+icon=@abs_top_builddir@/data/icon_ivi_clickdot.png
+path=@abs_top_builddir@/clients/weston-clickdot-ivi
+
+[ivi-launcher]
+workspace-id=3
+icon=@abs_top_builddir@/data/icon_ivi_simple-egl.png
+path=@abs_top_builddir@/clients/weston-simple-egl-ivi
+
+[ivi-launcher]
+workspace-id=3
+icon=@abs_top_builddir@/data/icon_ivi_simple-shm.png
+path=@abs_top_builddir@/clients/weston-simple-shm-ivi
+
+[ivi-launcher]
+workspace-id=3
+icon=@abs_top_builddir@/data/icon_ivi_smoke.png
+path=@abs_top_builddir@/clients/weston-smoke-ivi
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:07:10 UTC
Permalink
Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
clients/.gitignore | 5 ++++
clients/Makefile.am | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++
clients/simple-egl.c | 67 ++++++++++++++++++++++++++++++++++++++++++++--------
clients/simple-shm.c | 50 ++++++++++++++++++++++++++++++++++-----
clients/window.c | 42 ++++++++++++++++++++++++++++++--
5 files changed, 211 insertions(+), 18 deletions(-)

diff --git a/clients/.gitignore b/clients/.gitignore
index d23027c..41b3be3 100644
--- a/clients/.gitignore
+++ b/clients/.gitignore
@@ -20,6 +20,11 @@ weston-stacking
weston-subsurfaces
weston-transformed
weston-view
+weston-clickdot-ivi
+weston-flower-ivi
+weston-simple-egl-ivi
+weston-simple-shm-ivi
+weston-smoke-ivi

desktop-shell-client-protocol.h
desktop-shell-protocol.c
diff --git a/clients/Makefile.am b/clients/Makefile.am
index 4f8d4a6..4bbacb3 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -7,6 +7,11 @@ demo_clients = \
$(simple_clients_programs) \
$(simple_egl_clients_programs)

+if ENABLE_IVI_SHELL
+demo_clients += \
+ $(ivi_shell_clients_programs)
+endif
+
if INSTALL_DEMO_CLIENTS
bin_PROGRAMS += $(demo_clients)
else
@@ -246,6 +251,66 @@ endif

endif

+if ENABLE_IVI_SHELL
+noinst_LTLIBRARIES = libivitoytoolkit.la
+
+libivitoytoolkit_la_SOURCES = \
+ window.c \
+ window.h \
+ text-cursor-position-protocol.c \
+ text-cursor-position-client-protocol.h \
+ scaler-protocol.c \
+ scaler-client-protocol.h \
+ workspaces-protocol.c \
+ workspaces-client-protocol.h
+
+libivitoytoolkit_la_CPPFLAGS = $(AM_CPPFLAGS) -DENABLE_IVI_CLIENT
+
+libivitoytoolkit_la_LIBADD = \
+ $(CLIENT_LIBS) \
+ $(CAIRO_EGL_LIBS) \
+ ../shared/libshared-cairo.la -lrt -lm
+
+ivi_shell_clients_programs = \
+ weston-simple-egl-ivi \
+ weston-simple-shm-ivi \
+ weston-flower-ivi \
+ weston-smoke-ivi \
+ weston-clickdot-ivi
+
+weston_simple_egl_ivi_SOURCES = simple-egl.c \
+ ../ivi-shell/ivi-application-protocol.c \
+ ../ivi-shell/ivi-application-client-protocol.h
+weston_simple_egl_ivi_CPPFLAGS = $(SIMPLE_EGL_CLIENT_CFLAGS) -DENABLE_IVI_CLIENT
+weston_simple_egl_ivi_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
+
+weston_simple_shm_ivi_SOURCES = simple-shm.c \
+ ../shared/os-compatibility.c \
+ ../shared/os-compatibility.h \
+ ../ivi-shell/ivi-application-protocol.c \
+ ../ivi-shell/ivi-application-client-protocol.h
+weston_simple_shm_ivi_CPPFLAGS = $(SIMPLE_CLIENT_CFLAGS) -DENABLE_IVI_CLIENT
+weston_simple_shm_ivi_LDADD = $(SIMPLE_CLIENT_LIBS)
+
+weston_flower_ivi_SOURCES = flower.c \
+ ../ivi-shell/ivi-application-protocol.c \
+ ../ivi-shell/ivi-application-client-protocol.h
+weston_flower_ivi_CPPFLAGS = $(AM_CPPFLAGS) -DENABLE_IVI_CLIENT
+weston_flower_ivi_LDADD = libivitoytoolkit.la
+
+weston_smoke_ivi_SOURCES = smoke.c \
+ ../ivi-shell/ivi-application-protocol.c \
+ ../ivi-shell/ivi-application-client-protocol.h
+weston_smoke_ivi_CPPFLAGS = $(AM_CPPFLAGS) -DENABLE_IVI_CLIENT
+weston_smoke_ivi_LDADD = libivitoytoolkit.la
+
+weston_clickdot_ivi_SOURCES = clickdot.c \
+ ../ivi-shell/ivi-application-protocol.c \
+ ../ivi-shell/ivi-application-client-protocol.h
+weston_clickdot_ivi_CPPFLAGS = $(AM_CPPFLAGS) -DENABLE_IVI_CLIENT
+weston_clickdot_ivi_LDADD = libivitoytoolkit.la
+endif
+
wayland_protocoldir = $(top_srcdir)/protocol
include $(top_srcdir)/wayland-scanner.mk

diff --git a/clients/simple-egl.c b/clients/simple-egl.c
index 2c009ee..b06742f 100644
--- a/clients/simple-egl.c
+++ b/clients/simple-egl.c
@@ -38,6 +38,13 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>

+#ifdef ENABLE_IVI_CLIENT
+#include <sys/types.h>
+#include <unistd.h>
+#include "../ivi-shell/ivi-application-client-protocol.h"
+#define IVI_SURFACE_ID 9000
+#endif
+
#ifndef EGL_EXT_swap_buffers_with_damage
#define EGL_EXT_swap_buffers_with_damage 1
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
@@ -70,6 +77,9 @@ struct display {
EGLConfig conf;
} egl;
struct window *window;
+#ifdef ENABLE_IVI_CLIENT
+ struct ivi_application *ivi_application;
+#endif

PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
};
@@ -91,6 +101,9 @@ struct window {
struct wl_egl_window *native;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
+#ifdef ENABLE_IVI_CLIENT
+ struct ivi_surface *ivi_surface;
+#endif
EGLSurface egl_surface;
struct wl_callback *callback;
int fullscreen, configured, opaque, buffer_size, frame_sync;
@@ -250,7 +263,7 @@ init_gl(struct window *window)
}

glUseProgram(program);
-
+
window->gl.pos = 0;
window->gl.col = 1;

@@ -318,6 +331,12 @@ set_fullscreen(struct window *window, int fullscreen)
window->fullscreen = fullscreen;
window->configured = 0;

+ if (!window->shell_surface) {
+ handle_configure(window, NULL, 0, 250, 250);
+ window->configured = 1;
+ return;
+ }
+
if (fullscreen) {
wl_shell_surface_set_fullscreen(window->shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
@@ -341,13 +360,15 @@ create_surface(struct window *window)
{
struct display *display = window->display;
EGLBoolean ret;
-
+
window->surface = wl_compositor_create_surface(display->compositor);
- window->shell_surface = wl_shell_get_shell_surface(display->shell,
- window->surface);
+ if (display->shell)
+ window->shell_surface = wl_shell_get_shell_surface(display->shell,
+ window->surface);

- wl_shell_surface_add_listener(window->shell_surface,
- &shell_surface_listener, window);
+ if (window->shell_surface)
+ wl_shell_surface_add_listener(window->shell_surface,
+ &shell_surface_listener, window);

window->native =
wl_egl_window_create(window->surface,
@@ -357,8 +378,18 @@ create_surface(struct window *window)
eglCreateWindowSurface(display->egl.dpy,
display->egl.conf,
window->native, NULL);
+#ifdef ENABLE_IVI_CLIENT
+ uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
+ window->ivi_surface = ivi_application_surface_create(display->ivi_application,
+ id_ivisurf, window->surface);
+ if (window->ivi_surface == NULL) {
+ fprintf(stderr, "Failed to create ivi_client_surface\n");
+ abort();
+ }
+#endif

- wl_shell_surface_set_title(window->shell_surface, "simple-egl");
+ if (window->shell_surface)
+ wl_shell_surface_set_title(window->shell_surface, "simple-egl");

ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
window->egl_surface, window->display->egl.ctx);
@@ -381,7 +412,8 @@ destroy_surface(struct window *window)
eglDestroySurface(window->display->egl.dpy, window->egl_surface);
wl_egl_window_destroy(window->native);

- wl_shell_surface_destroy(window->shell_surface);
+ if (window->shell_surface)
+ wl_shell_surface_destroy(window->shell_surface);
wl_surface_destroy(window->surface);

if (window->callback)
@@ -542,7 +574,8 @@ pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
{
struct display *display = data;

- if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
+ if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED &&
+ display->window->shell_surface)
wl_shell_surface_move(display->window->shell_surface,
display->seat, serial);
}
@@ -568,7 +601,8 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
{
struct display *d = (struct display *)data;

- wl_shell_surface_move(d->window->shell_surface, d->seat, serial);
+ if (d->window->shell_surface)
+ wl_shell_surface_move(d->window->shell_surface, d->seat, serial);
}

static void
@@ -709,6 +743,11 @@ registry_handle_global(void *data, struct wl_registry *registry,
d->default_cursor =
wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
}
+#ifdef ENABLE_IVI_CLIENT
+ else if (strcmp(interface, "ivi_application") == 0) {
+ d->ivi_application = wl_registry_bind(registry, name, &ivi_application_interface, 1);
+ }
+#endif
}

static void
@@ -805,6 +844,11 @@ main(int argc, char **argv)

fprintf(stderr, "simple-egl exiting\n");

+#ifdef ENABLE_IVI_CLIENT
+ ivi_surface_destroy(window.ivi_surface);
+ ivi_application_destroy(window.display->ivi_application);
+#endif
+
destroy_surface(&window);
fini_egl(&display);

@@ -819,6 +863,9 @@ main(int argc, char **argv)
wl_compositor_destroy(display.compositor);

wl_registry_destroy(display.registry);
+#ifdef ENABLE_IVI_CLIENT
+ wl_display_roundtrip(display.display);
+#endif
wl_display_flush(display.display);
wl_display_disconnect(display.display);

diff --git a/clients/simple-shm.c b/clients/simple-shm.c
index 81bb54e..10acf5d 100644
--- a/clients/simple-shm.c
+++ b/clients/simple-shm.c
@@ -35,6 +35,12 @@
#include <wayland-client.h>
#include "../shared/os-compatibility.h"

+#ifdef ENABLE_IVI_CLIENT
+#include <sys/types.h>
+#include "../ivi-shell/ivi-application-client-protocol.h"
+#define IVI_SURFACE_ID 9000
+#endif
+
struct display {
struct wl_display *display;
struct wl_registry *registry;
@@ -42,6 +48,9 @@ struct display {
struct wl_shell *shell;
struct wl_shm *shm;
uint32_t formats;
+#ifdef ENABLE_IVI_CLIENT
+ struct ivi_application *ivi_application;
+#endif
};

struct buffer {
@@ -55,6 +64,9 @@ struct window {
int width, height;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
+#ifdef ENABLE_IVI_CLIENT
+ struct ivi_surface *ivi_surface;
+#endif
struct buffer buffers[2];
struct buffer *prev_buffer;
struct wl_callback *callback;
@@ -148,16 +160,29 @@ create_window(struct display *display, int width, int height)
window->width = width;
window->height = height;
window->surface = wl_compositor_create_surface(display->compositor);
- window->shell_surface = wl_shell_get_shell_surface(display->shell,
- window->surface);
+ if (display->shell)
+ window->shell_surface = wl_shell_get_shell_surface(display->shell,
+ window->surface);

if (window->shell_surface)
wl_shell_surface_add_listener(window->shell_surface,
&shell_surface_listener, window);

- wl_shell_surface_set_title(window->shell_surface, "simple-shm");
+#ifdef ENABLE_IVI_CLIENT
+ uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
+ window->ivi_surface = ivi_application_surface_create(display->ivi_application,
+ id_ivisurf, window->surface);
+ if (window->ivi_surface == NULL) {
+ fprintf(stderr, "Failed to create ivi_client_surface\n");
+ abort();
+ }
+#endif

- wl_shell_surface_set_toplevel(window->shell_surface);
+ if (window->shell_surface) {
+ wl_shell_surface_set_title(window->shell_surface, "simple-shm");
+
+ wl_shell_surface_set_toplevel(window->shell_surface);
+ }

return window;
}
@@ -173,7 +198,8 @@ destroy_window(struct window *window)
if (window->buffers[1].buffer)
wl_buffer_destroy(window->buffers[1].buffer);

- wl_shell_surface_destroy(window->shell_surface);
+ if (window->shell_surface)
+ wl_shell_surface_destroy(window->shell_surface);
wl_surface_destroy(window->surface);
free(window);
}
@@ -318,6 +344,11 @@ registry_handle_global(void *data, struct wl_registry *registry,
id, &wl_shm_interface, 1);
wl_shm_add_listener(d->shm, &shm_listener, d);
}
+#ifdef ENABLE_IVI_CLIENT
+ else if (strcmp(interface, "ivi_application") == 0) {
+ d->ivi_application = wl_registry_bind(registry, id, &ivi_application_interface, 1);
+ }
+#endif
}

static void
@@ -362,7 +393,7 @@ create_display(void)
}

wl_display_get_fd(display->display);
-
+
return display;
}

@@ -379,6 +410,9 @@ destroy_display(struct display *display)
wl_compositor_destroy(display->compositor);

wl_registry_destroy(display->registry);
+#ifdef ENABLE_IVI_CLIENT
+ wl_display_roundtrip(display->display);
+#endif
wl_display_flush(display->display);
wl_display_disconnect(display->display);
free(display);
@@ -420,6 +454,10 @@ main(int argc, char **argv)
ret = wl_display_dispatch(display->display);

fprintf(stderr, "simple-shm exiting\n");
+#ifdef ENABLE_IVI_CLIENT
+ ivi_surface_destroy(window->ivi_surface);
+ ivi_application_destroy(window->display->ivi_application);
+#endif
destroy_window(window);
destroy_display(display);

diff --git a/clients/window.c b/clients/window.c
index d8d79d0..928e405 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -71,6 +71,12 @@ typedef void *EGLContext;

#include "window.h"

+#ifdef ENABLE_IVI_CLIENT
+#include <sys/types.h>
+#include "../ivi-shell/ivi-application-client-protocol.h"
+#define IVI_SURFACE_ID 9000
+#endif
+
struct shm_pool;

struct global {
@@ -132,6 +138,9 @@ struct display {

int has_rgb565;
int seat_version;
+#ifdef ENABLE_IVI_CLIENT
+ struct ivi_application *ivi_application;
+#endif
};

enum {
@@ -252,6 +261,9 @@ struct window {

struct surface *main_surface;
struct wl_shell_surface *shell_surface;
+#ifdef ENABLE_IVI_CLIENT
+ struct ivi_surface *ivi_surface;
+#endif

struct window_frame *frame;

@@ -1403,6 +1415,18 @@ surface_create_surface(struct surface *surface, int dx, int dy, uint32_t flags)
struct display *display = surface->window->display;
struct rectangle allocation = surface->allocation;

+#ifdef ENABLE_IVI_CLIENT
+ if (!surface->toysurface) {
+ uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
+ surface->window->ivi_surface = ivi_application_surface_create(display->ivi_application,
+ id_ivisurf, surface->surface);
+ if (surface->window->ivi_surface == NULL) {
+ fprintf(stderr, "Failed to create ivi_client_surface\n");
+ abort();
+ }
+ }
+#endif
+
if (!surface->toysurface && display->dpy &&
surface->buffer_type == WINDOW_BUFFER_TYPE_EGL_WINDOW) {
surface->toysurface =
@@ -1518,6 +1542,11 @@ surface_destroy(struct surface *surface)
if (surface->toysurface)
surface->toysurface->destroy(surface->toysurface);

+#ifdef ENABLE_IVI_CLIENT
+ ivi_surface_destroy(surface->window->ivi_surface);
+ ivi_application_destroy(surface->window->display->ivi_application);
+#endif
+
wl_list_remove(&surface->link);
free(surface);
}
@@ -1532,7 +1561,7 @@ window_destroy(struct window *window)

wl_list_remove(&window->redraw_task.link);

- wl_list_for_each(input, &display->input_list, link) {
+ wl_list_for_each(input, &display->input_list, link) {
if (input->touch_focus == window)
input->touch_focus = NULL;
if (input->pointer_focus == window)
@@ -3039,7 +3068,7 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
wl_list_insert(&input->touch_point_list, &tp->link);

if (widget->touch_down_handler)
- (*widget->touch_down_handler)(widget, input,
+ (*widget->touch_down_handler)(widget, input,
serial, time, id,
sx, sy,
widget->user_data);
@@ -5017,6 +5046,11 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
wl_registry_bind(registry, id,
&wl_subcompositor_interface, 1);
}
+#ifdef ENABLE_IVI_CLIENT
+ else if (strcmp(interface, "ivi_application") == 0) {
+ d->ivi_application = wl_registry_bind(registry, id, &ivi_application_interface, 1);
+ }
+#endif

if (d->global_handler)
d->global_handler(d, id, interface, version, d->user_data);
@@ -5326,6 +5360,10 @@ display_destroy(struct display *display)

close(display->epoll_fd);

+#ifdef ENABLE_IVI_CLIENT
+ wl_display_roundtrip(display->display);
+#endif
+
if (!(display->display_fd_events & EPOLLERR) &&
!(display->display_fd_events & EPOLLHUP))
wl_display_flush(display->display);
--
1.8.3.1
Nobuhiko Tanibata
2014-03-06 10:27:30 UTC
Permalink
Hi,

This will add the following reference png files but I don't know whether I can send huge size of patch, around 650KB, to mailing list. These pngs file can be downloaded from here,

https://review.tizen.org/git/?p=profile/ivi/weston-ivi-shell.git;a=tree;f=data;h=600a549d874d7a54c16c3def09a4dad0853532a3;hb=e0f2e11fd31fd8b1201254a6c638c1e21d505ced

BR,
Nobuhiko

----------------------------------------

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---
data/background.png | Bin 0 -> 245579 bytes
data/fullscreen.png | Bin 0 -> 3406 bytes
data/home.png | Bin 0 -> 4629 bytes
data/icon_ivi_clickdot.png | Bin 0 -> 39523 bytes
data/icon_ivi_flower.png | Bin 0 -> 24475 bytes
data/icon_ivi_simple-egl.png | Bin 0 -> 29316 bytes
data/icon_ivi_simple-shm.png | Bin 0 -> 71120 bytes
data/icon_ivi_smoke.png | Bin 0 -> 46577 bytes
data/panel.png | Bin 0 -> 41955 bytes
data/random.png | Bin 0 -> 4891 bytes
data/sidebyside.png | Bin 0 -> 3929 bytes
data/tiling.png | Bin 0 -> 5620 bytes
12 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 data/background.png
create mode 100644 data/fullscreen.png
create mode 100644 data/home.png
create mode 100644 data/icon_ivi_clickdot.png
create mode 100644 data/icon_ivi_flower.png
create mode 100644 data/icon_ivi_simple-egl.png
create mode 100644 data/icon_ivi_simple-shm.png
create mode 100644 data/icon_ivi_smoke.png
create mode 100644 data/panel.png
create mode 100644 data/random.png
create mode 100644 data/sidebyside.png
create mode 100644 data/tiling.png
Nobuhiko Tanibata
2014-03-17 06:17:38 UTC
Permalink
Hi,

Thanks to review comments from mainling list. I refine patch series to
view them clearly.
I think some review comments remained there to be fixed. I will use this
thread.

BR,
Nobuhiko

2014-03-06 18:19 ? nobuhiko_tanibata ????????:
> Hi,
>
> This patch series adds a reference implementation of a shell for
> In-Vehicle Infotainment system; IVI, libraries on the shell to manage
> layout of User interface; UI, and samples how to use them. Before
> stepping in overview of patches, please let me explain background and
> purpose of this contribution.
>
> Background)
> I am working for prototyping a shell for In-Vehicle Infotainment; IVI
> in TIZEN IVI. This prototyping is being integrated to the TIZEN IVI.
>
> https://review.tizen.org/git/?p=profile/ivi/weston-ivi-shell.git;a=summary
>
> I am also working for GENIVI wayland-ivi-extension and several private
> projects with several Car Makers to apply a shell to its use case. The
> main use case on them is very similar with each other, which is based
> on a concept of Layer Management.
>
> http://projects.genivi.org/ivi-layer-management/node/13
>
> Purpose)
> I am contributing a reference for common use case of IVI mentioned in
> Background to avoid implementing same one for each user. The main use
> case is Layer Management to manage properties of surfaces and layer.
> Layer is used for grouping surfaces. In this patch series, I am
> contributing libweston-layout.so to support Layer management features
> with a set of interfaces which are defined based on
> ivi-layer-management from GENIVI. With libweston-layout.so, each shell
> developer of IVI can easily implement own shell.
>
> Overview)
> This patch series are mainly applied to new folder ?ivi-shell? like
> ?desktop-shell?. This patch series consists of 5 major parts,
>
> - ivi-shell.so : support ivi-application.xml protocol and
> initialization of libweston-layout.so. The ivi-application.xml defines
> simple interfaces; ?ivi_application::surface_create?. An interface
> ivi_application::surface_create? is used to tie ID to wl_surface from
> application. In IVI use case, such IDs are predefined at system design
> phase to control surface with business logic. For example, TV
> application shall be invisible in case of speed restriction.
>
> - libweston-layout.so: this shall be linked to ivi-shell.so to support
> layer management APIs internally. These APIs allows us to manage
> surfaces and layer by e.g. setting properties; position, visibility,
> opacity and rectangle of source to crop, and so on. This APIs
> internally uses weston_view as abstraction layer of compositor.
>
> - hmi-controller.so: a reference implementation how to use
> libweston-layout.so. It implement several protocols defined by
> ivi-hmi-controller.xml,
>
> 1/Requesting which surface is a part of User interfaces, e.g. a
> surface draw an icon from PNG files. According to request,
> hmi-controller layouts specified surfaces on a Screen by using
> libweston-layout.so.
> 2/Requesting layout change. There are 4 types of layout for a
> reference; tiling, side by side, full screen, and random.
> 3/Requesting displaying launchers. There are several pages to group
> icons which can be selected by motion of input.
> 4/Requesting animation moving from one page to another by motion of
> input.
> A reference how to use these protocols are implemented in
> hmi-controller-homescreen. A pthread sets up parts of UI and triggers
> layout change, showing launchers, and allowing hmi-controller to
> select pages of launchers by using ivi-hmi-controller.xml. This can be
> implemented in separated process, e.g. desktop-shell.c, as well.
>
> - Supporting ivi-application protocol to example in ?clients? folder.
> Add macro to compile ivi-application separately. Basically it uses the
> same code. For example, add macro: ENABLE_IVI_CLIENT to simple-egl.c
> for compiling weston-simple-egl-ivi at the same time.
>
> - Add reference weston.ini.in for ivi-shell in ivi-shell folder as
> well. It is referred by ivi-shell and hmi-controller.so to define
> several configurations. E.g. setting cursor, ID of surfaces and layers
> to be used by hmi-controller-homescreen, launchers; path to icons,
> binary, ID which page they are located.
>
>
> I am enclosing a pdf for overview of ivi-shell related parts. The pdf
> also mentions ivi-controller.so maintained here to keep compatibility
> with IVI layer manager.
>
> http://git.projects.genivi.org/?p=wayland-ivi-extension.git;a=summary
>
> It allow GENIVI graphic application to manage surfaces/layer outside
> of Weston process. However it is not purpose to do animation. Ideally,
> business logic shall be implemented inside of Weston process to reduce
> dispatch of process as much as possible.
>
>
> Best regards,
> Nobuhiko
Nobuhiko Tanibata
2014-03-17 06:21:42 UTC
Permalink
Hi,

Thanks to review comments from mainling list. I refine patch series to
view them clearly as v4.
I think some review comments remained there to be fixed. I will use this
thread.

BR,
Nobuhiko

2014-03-06 18:19 ? nobuhiko_tanibata ????????:
> Hi,
>
> This patch series adds a reference implementation of a shell for
> In-Vehicle Infotainment system; IVI, libraries on the shell to manage
> layout of User interface; UI, and samples how to use them. Before
> stepping in overview of patches, please let me explain background and
> purpose of this contribution.
>
> Background)
> I am working for prototyping a shell for In-Vehicle Infotainment; IVI
> in TIZEN IVI. This prototyping is being integrated to the TIZEN IVI.
>
> https://review.tizen.org/git/?p=profile/ivi/weston-ivi-shell.git;a=summary
>
> I am also working for GENIVI wayland-ivi-extension and several private
> projects with several Car Makers to apply a shell to its use case. The
> main use case on them is very similar with each other, which is based
> on a concept of Layer Management.
>
> http://projects.genivi.org/ivi-layer-management/node/13
>
> Purpose)
> I am contributing a reference for common use case of IVI mentioned in
> Background to avoid implementing same one for each user. The main use
> case is Layer Management to manage properties of surfaces and layer.
> Layer is used for grouping surfaces. In this patch series, I am
> contributing libweston-layout.so to support Layer management features
> with a set of interfaces which are defined based on
> ivi-layer-management from GENIVI. With libweston-layout.so, each shell
> developer of IVI can easily implement own shell.
>
> Overview)
> This patch series are mainly applied to new folder ?ivi-shell? like
> ?desktop-shell?. This patch series consists of 5 major parts,
>
> - ivi-shell.so : support ivi-application.xml protocol and
> initialization of libweston-layout.so. The ivi-application.xml defines
> simple interfaces; ?ivi_application::surface_create?. An interface
> ivi_application::surface_create? is used to tie ID to wl_surface from
> application. In IVI use case, such IDs are predefined at system design
> phase to control surface with business logic. For example, TV
> application shall be invisible in case of speed restriction.
>
> - libweston-layout.so: this shall be linked to ivi-shell.so to support
> layer management APIs internally. These APIs allows us to manage
> surfaces and layer by e.g. setting properties; position, visibility,
> opacity and rectangle of source to crop, and so on. This APIs
> internally uses weston_view as abstraction layer of compositor.
>
> - hmi-controller.so: a reference implementation how to use
> libweston-layout.so. It implement several protocols defined by
> ivi-hmi-controller.xml,
>
> 1/Requesting which surface is a part of User interfaces, e.g. a
> surface draw an icon from PNG files. According to request,
> hmi-controller layouts specified surfaces on a Screen by using
> libweston-layout.so.
> 2/Requesting layout change. There are 4 types of layout for a
> reference; tiling, side by side, full screen, and random.
> 3/Requesting displaying launchers. There are several pages to group
> icons which can be selected by motion of input.
> 4/Requesting animation moving from one page to another by motion of
> input.
> A reference how to use these protocols are implemented in
> hmi-controller-homescreen. A pthread sets up parts of UI and triggers
> layout change, showing launchers, and allowing hmi-controller to
> select pages of launchers by using ivi-hmi-controller.xml. This can be
> implemented in separated process, e.g. desktop-shell.c, as well.
>
> - Supporting ivi-application protocol to example in ?clients? folder.
> Add macro to compile ivi-application separately. Basically it uses the
> same code. For example, add macro: ENABLE_IVI_CLIENT to simple-egl.c
> for compiling weston-simple-egl-ivi at the same time.
>
> - Add reference weston.ini.in for ivi-shell in ivi-shell folder as
> well. It is referred by ivi-shell and hmi-controller.so to define
> several configurations. E.g. setting cursor, ID of surfaces and layers
> to be used by hmi-controller-homescreen, launchers; path to icons,
> binary, ID which page they are located.
>
>
> I am enclosing a pdf for overview of ivi-shell related parts. The pdf
> also mentions ivi-controller.so maintained here to keep compatibility
> with IVI layer manager.
>
> http://git.projects.genivi.org/?p=wayland-ivi-extension.git;a=summary
>
> It allow GENIVI graphic application to manage surfaces/layer outside
> of Weston process. However it is not purpose to do animation. Ideally,
> business logic shall be implemented inside of Weston process to reduce
> dispatch of process as much as possible.
>
>
> Best regards,
> Nobuhiko
Nobuhiko Tanibata
2014-03-17 06:23:22 UTC
Permalink
Add interface ivi_application, which creates ivi_surface objects tied
to a given wl_surface with a given id. The given id can be used in a
shell to identify which application is assigned to a wl_surface and
layout the surface wherever the shell wants. ivi_surface objects can
be used to receive status of wl_surface in the scenegraph of the
compositor.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- Rename "error" to "warning" because meaning of "error" in wayland is fatal.

Changes for v3:
- Move "warning" from ivi_application to ivi_surface.
- Squash Makefile.
- Add description to ivi_surface:destroy.
- Update description of ivi_application:surface_create.

Changes for v4:
- Remove detail description of server side from ivi_surface::destroy
- Add clear discripton what client shall do if it encounters warning in ivi_surface
::warning.
- Add decription what happens when client tries to tie a wl_surface to multiple
ivi_surfaces.

protocol/Makefile.am | 3 +-
protocol/ivi-application.xml | 99 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 101 insertions(+), 1 deletion(-)
create mode 100644 protocol/ivi-application.xml

diff --git a/protocol/Makefile.am b/protocol/Makefile.am
index 5e331a7..9913f16 100644
--- a/protocol/Makefile.am
+++ b/protocol/Makefile.am
@@ -8,7 +8,8 @@ protocol_sources = \
text-cursor-position.xml \
wayland-test.xml \
xdg-shell.xml \
- scaler.xml
+ scaler.xml \
+ ivi-application.xml

if HAVE_XMLLINT
.PHONY: validate
diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
new file mode 100644
index 0000000..37ad489
--- /dev/null
+++ b/protocol/ivi-application.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ivi_application">
+
+ <copyright>
+ Copyright (C) 2013 DENSO CORPORATION
+ Copyright (c) 2013 BMW Car IT GmbH
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ </copyright>
+
+ <interface name="ivi_surface" version="1">
+ <description summary="application interface to surface in ivi compositor"/>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy ivi_surface">
+ This removes link from surface_id to wl_surface and destroys ivi_surface.
+ </description>
+ </request>
+
+ <event name="visibility">
+ <description summary="visibility of surface in ivi compositor has changed">
+ The new visibility state is provided in argument visibility.
+ If visibility is 0, the surface has become invisible.
+ If visibility is not 0, the surface has become visible.
+ </description>
+ <arg name="visibility" type="int"/>
+ </event>
+
+ <enum name="warning_code">
+ <description summary="possible warning codes returned by ivi compositor">
+ These warning codes define all possible warning codes returned by ivi compositor
+ on server-side warnings.
+ invalid_wl_surface: invalid wl_surface is set. This happens if wl_surface is destroyed before this.
+ surface_id_in_use: surface_id is already assigned by another application.
+ </description>
+ <entry name="invalid_wl_surface" value="1" summary="wl_surface is invalid"/>
+ <entry name="surface_id_in_use" value="2" summary="surface_id is in use and can not be shared"/>
+ </enum>
+
+ <event name="warning">
+ <description summary="server-side warning detected">
+ The ivi compositor encountered warning while processing a request by this
+ application. The warning is defined by argument warning_code and optional
+ warning_text. If the warning is detected, client shall destroy the ivi_surface
+ object.
+
+ When ivi compositor encounters warnings, a request is canceled and there is no
+ mapping from id_surface/wl_surface to this ivi_surface. Even if there is no
+ mapping but destroying this ivi_surface is recommended.
+ </description>
+ <arg name="warning_code" type="int"/>
+ <arg name="warning_text" type="string" allow-null="true"/>
+ </event>
+
+ </interface>
+
+ <interface name="ivi_application" version="1">
+ <description summary="interface for ivi applications to use ivi compositor features"/>
+
+ <request name="surface_create">
+ <description summary="create ivi_surface with numeric ID in ivi compositor">
+ surface_create will create a interface:ivi_surface with numeric ID; surface_id in
+ ivi compositor. These surface_ids are defined as unique in the system to identify
+ it inside of ivi compositor. The ivi compositor implements business logic how to
+ set properties of the surface with surface_id according to status of the system.
+ E.g. a unique ID for Car Navigation application is used for implementing special
+ logic of the application about where it shall be located.
+
+ Created ivi_surface notifies warnings when following situation happens,
+ - Invalid wl_surface is set. This happen if wl_surface is destroy before this.
+ - surface_id is already assigned by another application.
+ If a client sets a wl_surface to multiple id_surfaces, no warning is issued. Property
+ of the surface can be controlled by multiple ivi_surface. However this case shall
+ be avoided by a client.
+ </description>
+ <arg name="id_surface" type="uint"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="id" type="new_id" interface="ivi_surface"/>
+ </request>
+
+ </interface>
+
+</protocol>
--
1.8.3.1
Pekka Paalanen
2014-04-23 10:40:37 UTC
Permalink
Hi,

it's been a long while since I have looked at this, but I got a bit of
time to come back. I hope you haven't abandoned this effort yet. :-)

I looked at the PDF from your post on March 6th, 2014, and some of my
own comments I gave at that time to recall what this was about, but I
probably still forgot something.

New comments below. I started by reading the global interface, and
moved on to ivi_surface after it, so the comments might seem
temporally strange if you read just top-down.


On Mon, 17 Mar 2014 15:23:22 +0900
Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:

> Add interface ivi_application, which creates ivi_surface objects tied
> to a given wl_surface with a given id. The given id can be used in a
> shell to identify which application is assigned to a wl_surface and
> layout the surface wherever the shell wants. ivi_surface objects can
> be used to receive status of wl_surface in the scenegraph of the
> compositor.
>
> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
> ---
>
> Changes for v2:
> - Rename "error" to "warning" because meaning of "error" in wayland is fatal.
>
> Changes for v3:
> - Move "warning" from ivi_application to ivi_surface.
> - Squash Makefile.
> - Add description to ivi_surface:destroy.
> - Update description of ivi_application:surface_create.
>
> Changes for v4:
> - Remove detail description of server side from ivi_surface::destroy
> - Add clear discripton what client shall do if it encounters warning in ivi_surface
> ::warning.
> - Add decription what happens when client tries to tie a wl_surface to multiple
> ivi_surfaces.
>
> protocol/Makefile.am | 3 +-
> protocol/ivi-application.xml | 99 ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 101 insertions(+), 1 deletion(-)
> create mode 100644 protocol/ivi-application.xml
>
> diff --git a/protocol/Makefile.am b/protocol/Makefile.am
> index 5e331a7..9913f16 100644
> --- a/protocol/Makefile.am
> +++ b/protocol/Makefile.am
> @@ -8,7 +8,8 @@ protocol_sources = \
> text-cursor-position.xml \
> wayland-test.xml \
> xdg-shell.xml \
> - scaler.xml
> + scaler.xml \
> + ivi-application.xml
>
> if HAVE_XMLLINT
> .PHONY: validate
> diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
> new file mode 100644
> index 0000000..37ad489
> --- /dev/null
> +++ b/protocol/ivi-application.xml
> @@ -0,0 +1,99 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<protocol name="ivi_application">
> +
> + <copyright>
> + Copyright (C) 2013 DENSO CORPORATION
> + Copyright (c) 2013 BMW Car IT GmbH
> +
> + Permission is hereby granted, free of charge, to any person obtaining a copy
> + of this software and associated documentation files (the "Software"), to deal
> + in the Software without restriction, including without limitation the rights
> + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + copies of the Software, and to permit persons to whom the Software is
> + furnished to do so, subject to the following conditions:
> +
> + The above copyright notice and this permission notice shall be included in
> + all copies or substantial portions of the Software.
> +
> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + THE SOFTWARE.
> + </copyright>
> +
> + <interface name="ivi_surface" version="1">
> + <description summary="application interface to surface in ivi compositor"/>
> +
> + <request name="destroy" type="destructor">
> + <description summary="destroy ivi_surface">
> + This removes link from surface_id to wl_surface and destroys ivi_surface.
> + </description>
> + </request>
> +
> + <event name="visibility">
> + <description summary="visibility of surface in ivi compositor has changed">
> + The new visibility state is provided in argument visibility.
> + If visibility is 0, the surface has become invisible.
> + If visibility is not 0, the surface has become visible.
> + </description>
> + <arg name="visibility" type="int"/>
> + </event>
> +
> + <enum name="warning_code">
> + <description summary="possible warning codes returned by ivi compositor">
> + These warning codes define all possible warning codes returned by ivi compositor

Codes define codes? :-)

> + on server-side warnings.
> + invalid_wl_surface: invalid wl_surface is set. This happens if wl_surface is destroyed before this.

Ooh, does this mean that invalid_wl_surface is emitted if wl_surface is
destroyed before the ivi_surface? Try to use more nouns and less
pronouns in specification language to keep things explicit.

I was about ask what happens if the wl_surface gets destroyed first.

> + surface_id_in_use: surface_id is already assigned by another application.
> + </description>
> + <entry name="invalid_wl_surface" value="1" summary="wl_surface is invalid"/>
> + <entry name="surface_id_in_use" value="2" summary="surface_id is in use and can not be shared"/>
> + </enum>
> +
> + <event name="warning">
> + <description summary="server-side warning detected">
> + The ivi compositor encountered warning while processing a request by this
> + application. The warning is defined by argument warning_code and optional
> + warning_text. If the warning is detected, client shall destroy the ivi_surface
> + object.
> +
> + When ivi compositor encounters warnings, a request is canceled and there is no
> + mapping from id_surface/wl_surface to this ivi_surface. Even if there is no
> + mapping but destroying this ivi_surface is recommended.

I would propose a slightly different wording here, which may or may not
be what you intended above.

"When a warning event is sent, the compositor turns the ivi_surface
object inert. The ivi_surface will not deliver further events, all
requests on it are ignored except 'destroy', and the association to the
surface_id is removed. The client should destroy the ivi_surface
object. If an inert ivi_surface object is used as an argument to any
other object's request, that request will [produce a fatal error /
produce a warning / be ignored]."

There are no requests other than 'destroy' on ivi_surface, but it is
better to be explicit just in case later someone adds a new request. On
the final part, you can pick what suits best, or say that the effect is
undefined.

> + </description>
> + <arg name="warning_code" type="int"/>
> + <arg name="warning_text" type="string" allow-null="true"/>
> + </event>
> +
> + </interface>
> +
> + <interface name="ivi_application" version="1">
> + <description summary="interface for ivi applications to use ivi compositor features"/>

Could mention that this is a global interface, isn't it?

> + <request name="surface_create">
> + <description summary="create ivi_surface with numeric ID in ivi compositor">
> + surface_create will create a interface:ivi_surface with numeric ID; surface_id in
> + ivi compositor. These surface_ids are defined as unique in the system to identify
> + it inside of ivi compositor. The ivi compositor implements business logic how to
> + set properties of the surface with surface_id according to status of the system.
> + E.g. a unique ID for Car Navigation application is used for implementing special
> + logic of the application about where it shall be located.
> +
> + Created ivi_surface notifies warnings when following situation happens,
> + - Invalid wl_surface is set. This happen if wl_surface is destroy before this.

How is it possible to destroy the wl_surface before issuing a
ivi_application.surface_create request? IOW, I cannot understand when a
wl_surface could be invalid due to "destroy". But it could be if the
wl_surface already has a role.

> + - surface_id is already assigned by another application.
> + If a client sets a wl_surface to multiple id_surfaces, no warning is issued. Property
> + of the surface can be controlled by multiple ivi_surface. However this case shall
> + be avoided by a client.

By id_surface, do you mean creating multiple ivi_surface objects with
the same or different surface_id for a single wl_surface? Would it ever
make any sense to do that?

Is it legal or illegal to do that? If it is illegal, there should be a
fatal protocol error. I know you prefer non-fatal warnings, but even
Wayland core has fatal errors like for invalid object id. I would think
that creating several ivi_surfaces for the same wl_surface would be a
similar problem as use-after-free producing an invalid object id, if it
really is illegal.

Also, if ivi_application.surface_create assigns a role to a wl_surface,
then you cannot have several ivi_surfaces referencing the same
wl_surface.

In Weston, a role is identified by weston_surface::configure function
pointer. More conceptually, a role defines how the surface behaves on
screen: cursor surface moves with the pointer, ivi_surface is
controlled by your... ivi-controller or something. In principle,
without a role, a surface cannot be shown at all because the compositor
does not know how or when to show it.

> + </description>
> + <arg name="id_surface" type="uint"/>

id_surface here, surface_id in the doc; maybe pick one form, and use
that everywhere?

I wonder, could we use a more specific term for the ID? Would "ivi_id"
be unambiguous? So we could talk about surface's ivi_id, as opposed to
surface_id which is not obviously an IVI concept. Every Wayland protocol
object has an id, and I would like avoid any chances of confusing
wl_surface id with ivi_id.

> + <arg name="surface" type="object" interface="wl_surface"/>
> + <arg name="id" type="new_id" interface="ivi_surface"/>
> + </request>
> +
> + </interface>
> +
> +</protocol>

This is looking good, mostly just some details in the wording to be
tuned. :-)

I will see if I can review more of the patches, but I would also
suggest the following, in case you are still interested in pushing this
upstream.

Wait for Weston 1.5 to be released. We are currently in freeze, so
there is no point in re-sending until that is done. Check that the 1.5
stable branch has been created, or at least the release has been made,
before you rebase and re-send this series.


Thanks,
pq
Nobuhiko Tanibata
2014-04-25 13:34:27 UTC
Permalink
2014-04-23 19:40 ? Pekka Paalanen ????????:
> Hi,
>
> it's been a long while since I have looked at this, but I got a bit of
> time to come back. I hope you haven't abandoned this effort yet. :-)
>
> I looked at the PDF from your post on March 6th, 2014, and some of my
> own comments I gave at that time to recall what this was about, but I
> probably still forgot something.
>
> New comments below. I started by reading the global interface, and
> moved on to ivi_surface after it, so the comments might seem
> temporally strange if you read just top-down.
>
>
> On Mon, 17 Mar 2014 15:23:22 +0900
> Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp> wrote:
>
>> Add interface ivi_application, which creates ivi_surface objects tied
>> to a given wl_surface with a given id. The given id can be used in a
>> shell to identify which application is assigned to a wl_surface and
>> layout the surface wherever the shell wants. ivi_surface objects can
>> be used to receive status of wl_surface in the scenegraph of the
>> compositor.
>>
>> Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
>> ---
>>
>> Changes for v2:
>> - Rename "error" to "warning" because meaning of "error" in wayland
>> is fatal.
>>
>> Changes for v3:
>> - Move "warning" from ivi_application to ivi_surface.
>> - Squash Makefile.
>> - Add description to ivi_surface:destroy.
>> - Update description of ivi_application:surface_create.
>>
>> Changes for v4:
>> - Remove detail description of server side from
>> ivi_surface::destroy
>> - Add clear discripton what client shall do if it encounters
>> warning in ivi_surface
>> ::warning.
>> - Add decription what happens when client tries to tie a wl_surface
>> to multiple
>> ivi_surfaces.
>>
>> protocol/Makefile.am | 3 +-
>> protocol/ivi-application.xml | 99
>> ++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 101 insertions(+), 1 deletion(-)
>> create mode 100644 protocol/ivi-application.xml
>>
>> diff --git a/protocol/Makefile.am b/protocol/Makefile.am
>> index 5e331a7..9913f16 100644
>> --- a/protocol/Makefile.am
>> +++ b/protocol/Makefile.am
>> @@ -8,7 +8,8 @@ protocol_sources = \
>> text-cursor-position.xml \
>> wayland-test.xml \
>> xdg-shell.xml \
>> - scaler.xml
>> + scaler.xml \
>> + ivi-application.xml
>>
>> if HAVE_XMLLINT
>> .PHONY: validate
>> diff --git a/protocol/ivi-application.xml
>> b/protocol/ivi-application.xml
>> new file mode 100644
>> index 0000000..37ad489
>> --- /dev/null
>> +++ b/protocol/ivi-application.xml
>> @@ -0,0 +1,99 @@
>> +<?xml version="1.0" encoding="UTF-8"?>
>> +<protocol name="ivi_application">
>> +
>> + <copyright>
>> + Copyright (C) 2013 DENSO CORPORATION
>> + Copyright (c) 2013 BMW Car IT GmbH
>> +
>> + Permission is hereby granted, free of charge, to any person
>> obtaining a copy
>> + of this software and associated documentation files (the
>> "Software"), to deal
>> + in the Software without restriction, including without limitation
>> the rights
>> + to use, copy, modify, merge, publish, distribute, sublicense,
>> and/or sell
>> + copies of the Software, and to permit persons to whom the
>> Software is
>> + furnished to do so, subject to the following conditions:
>> +
>> + The above copyright notice and this permission notice shall be
>> included in
>> + all copies or substantial portions of the Software.
>> +
>> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL THE
>> + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> DEALINGS IN
>> + THE SOFTWARE.
>> + </copyright>
>> +
>> + <interface name="ivi_surface" version="1">
>> + <description summary="application interface to surface in ivi
>> compositor"/>
>> +
>> + <request name="destroy" type="destructor">
>> + <description summary="destroy ivi_surface">
>> + This removes link from surface_id to wl_surface and
>> destroys ivi_surface.
>> + </description>
>> + </request>
>> +
>> + <event name="visibility">
>> + <description summary="visibility of surface in ivi
>> compositor has changed">
>> + The new visibility state is provided in argument
>> visibility.
>> + If visibility is 0, the surface has become invisible.
>> + If visibility is not 0, the surface has become
>> visible.
>> + </description>
>> + <arg name="visibility" type="int"/>
>> + </event>
>> +
>> + <enum name="warning_code">
>> + <description summary="possible warning codes returned by
>> ivi compositor">
>> + These warning codes define all possible warning codes
>> returned by ivi compositor
>
> Codes define codes? :-)
>
>> + on server-side warnings.
>> + invalid_wl_surface: invalid wl_surface is set. This
>> happens if wl_surface is destroyed before this.
>
> Ooh, does this mean that invalid_wl_surface is emitted if wl_surface is
> destroyed before the ivi_surface? Try to use more nouns and less
> pronouns in specification language to keep things explicit.
>
> I was about ask what happens if the wl_surface gets destroyed first.
>
>> + surface_id_in_use: surface_id is already assigned by
>> another application.
>> + </description>
>> + <entry name="invalid_wl_surface" value="1"
>> summary="wl_surface is invalid"/>
>> + <entry name="surface_id_in_use" value="2"
>> summary="surface_id is in use and can not be shared"/>
>> + </enum>
>> +
>> + <event name="warning">
>> + <description summary="server-side warning detected">
>> + The ivi compositor encountered warning while
>> processing a request by this
>> + application. The warning is defined by argument
>> warning_code and optional
>> + warning_text. If the warning is detected, client
>> shall destroy the ivi_surface
>> + object.
>> +
>> + When ivi compositor encounters warnings, a request is
>> canceled and there is no
>> + mapping from id_surface/wl_surface to this
>> ivi_surface. Even if there is no
>> + mapping but destroying this ivi_surface is
>> recommended.
>
> I would propose a slightly different wording here, which may or may not
> be what you intended above.
>
> "When a warning event is sent, the compositor turns the ivi_surface
> object inert. The ivi_surface will not deliver further events, all
> requests on it are ignored except 'destroy', and the association to the
> surface_id is removed. The client should destroy the ivi_surface
> object. If an inert ivi_surface object is used as an argument to any
> other object's request, that request will [produce a fatal error /
> produce a warning / be ignored]."
>
> There are no requests other than 'destroy' on ivi_surface, but it is
> better to be explicit just in case later someone adds a new request. On
> the final part, you can pick what suits best, or say that the effect is
> undefined.
>
>> + </description>
>> + <arg name="warning_code" type="int"/>
>> + <arg name="warning_text" type="string"
>> allow-null="true"/>
>> + </event>
>> +
>> + </interface>
>> +
>> + <interface name="ivi_application" version="1">
>> + <description summary="interface for ivi applications to use
>> ivi compositor features"/>
>
> Could mention that this is a global interface, isn't it?
>
>> + <request name="surface_create">
>> + <description summary="create ivi_surface with numeric ID
>> in ivi compositor">
>> + surface_create will create a interface:ivi_surface
>> with numeric ID; surface_id in
>> + ivi compositor. These surface_ids are defined as
>> unique in the system to identify
>> + it inside of ivi compositor. The ivi compositor
>> implements business logic how to
>> + set properties of the surface with surface_id
>> according to status of the system.
>> + E.g. a unique ID for Car Navigation application is
>> used for implementing special
>> + logic of the application about where it shall be
>> located.
>> +
>> + Created ivi_surface notifies warnings when following
>> situation happens,
>> + - Invalid wl_surface is set. This happen if
>> wl_surface is destroy before this.
>
> How is it possible to destroy the wl_surface before issuing a
> ivi_application.surface_create request? IOW, I cannot understand when a
> wl_surface could be invalid due to "destroy". But it could be if the
> wl_surface already has a role.
>
>> + - surface_id is already assigned by another
>> application.
>> + If a client sets a wl_surface to multiple
>> id_surfaces, no warning is issued. Property
>> + of the surface can be controlled by multiple
>> ivi_surface. However this case shall
>> + be avoided by a client.
>
> By id_surface, do you mean creating multiple ivi_surface objects with
> the same or different surface_id for a single wl_surface? Would it ever
> make any sense to do that?
>
> Is it legal or illegal to do that? If it is illegal, there should be a
> fatal protocol error. I know you prefer non-fatal warnings, but even
> Wayland core has fatal errors like for invalid object id. I would think
> that creating several ivi_surfaces for the same wl_surface would be a
> similar problem as use-after-free producing an invalid object id, if it
> really is illegal.
>
> Also, if ivi_application.surface_create assigns a role to a wl_surface,
> then you cannot have several ivi_surfaces referencing the same
> wl_surface.
>
> In Weston, a role is identified by weston_surface::configure function
> pointer. More conceptually, a role defines how the surface behaves on
> screen: cursor surface moves with the pointer, ivi_surface is
> controlled by your... ivi-controller or something. In principle,
> without a role, a surface cannot be shown at all because the compositor
> does not know how or when to show it.
>
>> + </description>
>> + <arg name="id_surface" type="uint"/>
>
> id_surface here, surface_id in the doc; maybe pick one form, and use
> that everywhere?
>
> I wonder, could we use a more specific term for the ID? Would "ivi_id"
> be unambiguous? So we could talk about surface's ivi_id, as opposed to
> surface_id which is not obviously an IVI concept. Every Wayland
> protocol
> object has an id, and I would like avoid any chances of confusing
> wl_surface id with ivi_id.
>
>> + <arg name="surface" type="object"
>> interface="wl_surface"/>
>> + <arg name="id" type="new_id" interface="ivi_surface"/>
>> + </request>
>> +
>> + </interface>
>> +
>> +</protocol>
>
> This is looking good, mostly just some details in the wording to be
> tuned. :-)
>
> I will see if I can review more of the patches, but I would also
> suggest the following, in case you are still interested in pushing this
> upstream.
>
> Wait for Weston 1.5 to be released. We are currently in freeze, so
> there is no point in re-sending until that is done. Check that the 1.5
> stable branch has been created, or at least the release has been made,
> before you rebase and re-send this series.
>
Hi pq,

Yes, I am still interested in pushing them. I will rabase them and
re-send them after weston 1.5 branch has been created.
I am also confirming your comments for other patches as well. Btw, do
you have a date when the branch is made?

BR,
Nobuhiko
>
> Thanks,
> pq
Pekka Paalanen
2014-04-25 16:05:38 UTC
Permalink
On Fri, 25 Apr 2014 22:34:27 +0900
Nobuhiko Tanibata <nobuhiko_tanibata at xddp.denso.co.jp> wrote:

> 2014-04-23 19:40 ? Pekka Paalanen ????????:
> > This is looking good, mostly just some details in the wording
> > to be tuned. :-)
> >
> > I will see if I can review more of the patches, but I would also
> > suggest the following, in case you are still interested in
> > pushing this upstream.
> >
> > Wait for Weston 1.5 to be released. We are currently in freeze,
> > so there is no point in re-sending until that is done. Check
> > that the 1.5 stable branch has been created, or at least the
> > release has been made, before you rebase and re-send this
> > series.
> >
> Hi pq,
>
> Yes, I am still interested in pushing them. I will rabase them
> and re-send them after weston 1.5 branch has been created.
> I am also confirming your comments for other patches as well.
> Btw, do you have a date when the branch is made?

Hi,

good to hear. :-)

I don't know of a date, but I suppose early May, perhaps.


Thanks,
pq
Nobuhiko Tanibata
2014-05-20 04:13:14 UTC
Permalink
2014-04-26 01:05 ? Pekka Paalanen ????????:
> On Fri, 25 Apr 2014 22:34:27 +0900
> Nobuhiko Tanibata <nobuhiko_tanibata at xddp.denso.co.jp> wrote:
>
>> 2014-04-23 19:40 ? Pekka Paalanen ????????:
>> > This is looking good, mostly just some details in the wording
>> > to be tuned. :-)
>> >
>> > I will see if I can review more of the patches, but I would also
>> > suggest the following, in case you are still interested in
>> > pushing this upstream.
>> >
>> > Wait for Weston 1.5 to be released. We are currently in freeze,
>> > so there is no point in re-sending until that is done. Check
>> > that the 1.5 stable branch has been created, or at least the
>> > release has been made, before you rebase and re-send this
>> > series.
>> >
>> Hi pq,
>>
>> Yes, I am still interested in pushing them. I will rabase them
>> and re-send them after weston 1.5 branch has been created.
>> I am also confirming your comments for other patches as well.
>> Btw, do you have a date when the branch is made?
>
> Hi,
>
> good to hear. :-)
>
> I don't know of a date, but I suppose early May, perhaps.
>

Hi,

I am re-sending them which are re-based based on Weston 1.5.
Additionally, I applied review comments from pq. Thank you for many
comments.
They are very use full for me!

BR,
Nobuhiko

>
> Thanks,
> pq
Nobuhiko Tanibata
2014-05-20 04:26:23 UTC
Permalink
ivi_applicatoin extension creates ivi_surface objects tied
to a given wl_surface with a given id. The given id can be used in a
shell to identify which application is assigned to a wl_surface and
layout the surface wherever the shell wants. ivi_surface objects can
be used to receive status of wl_surface in the scenegraph of the
compositor.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- Rename "error" to "warning" because meaning of "error" in wayland is fatal.

Changes for v3:
- Move "warning" from ivi_application to ivi_surface.
- Squash Makefile.
- Add description to ivi_surface:destroy.
- Update description of ivi_application:surface_create.

Changes for v4:
- Remove detail description of server side from ivi_surface::destroy
- Add clear discripton what client shall do if it encounters warning in ivi_surface
::warning.
- Add decription what happens when client tries to tie a wl_surface to multiple
ivi_surfaces.

Changes for v5:
- apply review comments from mailing list

protocol/Makefile.am | 3 +-
protocol/ivi-application.xml | 101 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 103 insertions(+), 1 deletion(-)
create mode 100644 protocol/ivi-application.xml

diff --git a/protocol/Makefile.am b/protocol/Makefile.am
index 5e331a7..9913f16 100644
--- a/protocol/Makefile.am
+++ b/protocol/Makefile.am
@@ -8,7 +8,8 @@ protocol_sources = \
text-cursor-position.xml \
wayland-test.xml \
xdg-shell.xml \
- scaler.xml
+ scaler.xml \
+ ivi-application.xml

if HAVE_XMLLINT
.PHONY: validate
diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
new file mode 100644
index 0000000..833fd38
--- /dev/null
+++ b/protocol/ivi-application.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ivi_application">
+
+ <copyright>
+ Copyright (C) 2013 DENSO CORPORATION
+ Copyright (c) 2013 BMW Car IT GmbH
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ </copyright>
+
+ <interface name="ivi_surface" version="1">
+ <description summary="application interface to surface in ivi compositor"/>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy ivi_surface">
+ This removes link from ivi_id to wl_surface and destroys ivi_surface.
+ </description>
+ </request>
+
+ <event name="visibility">
+ <description summary="visibility of surface in ivi compositor has changed">
+ The new visibility state is provided in argument visibility.
+ If visibility is 0, the surface has become invisible.
+ If visibility is not 0, the surface has become visible.
+ </description>
+ <arg name="visibility" type="int"/>
+ </event>
+
+ <enum name="warning_code">
+ <description summary="possible warning codes returned by ivi compositor">
+ These define all possible warning codes returned by ivi compositor on server-side warnings.
+ invalid_wl_surface:
+ - wl_surface already has a another role.
+ - wl_surface is destroyed before the ivi_surface is destroyed.
+ ivi_id_in_use: ivi_id is already assigned by another application.
+ </description>
+ <entry name="invalid_wl_surface" value="1" summary="wl_surface is invalid"/>
+ <entry name="ivi_id_in_use" value="2" summary="ivi_id is in use and can not be shared"/>
+ </enum>
+
+ <event name="warning">
+ <description summary="server-side warning detected">
+ The ivi compositor encountered warning while processing a request by this
+ application. The warning is defined by argument warning_code and optional
+ warning_text. If the warning is detected, client shall destroy the ivi_surface
+ object.
+
+ When a warning event is sent, the compositor turns the ivi_surface object inert.
+ The ivi_surface will not deliver further events, all requests on it are ignored
+ except 'destroy', and the association to the ivi_id is removed. The client
+ should destroy the ivi_surface object. If an inert ivi_surface object is used as
+ an argument to any other object's request, that request will [produce a fatal
+ error / produce a warning / be ignored].
+ </description>
+ <arg name="warning_code" type="int"/>
+ <arg name="warning_text" type="string" allow-null="true"/>
+ </event>
+
+ </interface>
+
+ <interface name="ivi_application" version="1">
+ <description summary="create ivi-style surfaces">
+ This interface is implemented by servers that provide desktop-style user interfaces.
+ It allows clients to associate a ivi_surface with a basic surface.
+ </description>
+
+ <request name="surface_create">
+ <description summary="create ivi_surface with numeric ID in ivi compositor">
+ surface_create will create a interface:ivi_surface with numeric ID; ivi_id in
+ ivi compositor. These ivi_ids are defined as unique in the system to identify
+ it inside of ivi compositor. The ivi compositor implements business logic how to
+ set properties of the surface with ivi_id according to status of the system.
+ E.g. a unique ID for Car Navigation application is used for implementing special
+ logic of the application about where it shall be located.
+ if a wl_surface which already has another role is set, the server regards this as
+ error and disconnects the client.
+ </description>
+ <arg name="ivi_id" type="uint"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="id" type="new_id" interface="ivi_surface"/>
+ </request>
+
+ </interface>
+
+</protocol>
--
1.8.3.1
Nobuhiko Tanibata
2014-05-20 04:28:51 UTC
Permalink
In-Vehicle Infotainment system traditionally manages surfaces with global
identification. A protocol, ivi_application, supports such a feature by
implementing a request, ivi_application::surface_creation defined in
ivi_application.xml.

The ivi-shell explicitly loads ivi-layout.so and a module to add business
logic like how to layout surfaces by using ivi-layout APIs.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- apply review comments of mailing list.
- squash update of Makefile into this patch.
- move this patch after patch of weston-layout.
- support inherit propoerties of id_surface when client attaches another
wl_surface with id_surface after destroying ivi_surface once.

Changes for v3:
- squash internal method, configure, to ivi_shell_surface_configure.

Changes for v4:
- nothing. Version number aligned to the first patch

Changes for v5:
- rebase weston v1.5 branch
- apply review comments from mailing list

Makefile.am | 22 +++
configure.ac | 12 ++
ivi-shell/ivi-layout.h | 75 +++++++++
ivi-shell/ivi-shell.c | 414 +++++++++++++++++++++++++++++++++++++++++++++++++
ivi-shell/ivi-shell.h | 35 +++++
5 files changed, 558 insertions(+)
create mode 100644 ivi-shell/ivi-layout.h
create mode 100644 ivi-shell/ivi-shell.c
create mode 100644 ivi-shell/ivi-shell.h

diff --git a/Makefile.am b/Makefile.am
index 343adc6..279fffc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -700,6 +700,28 @@ nodist_fullscreen_shell_la_SOURCES = \
BUILT_SOURCES += $(nodist_fullscreen_shell_la_SOURCES)
endif

+if ENABLE_IVI_SHELL
+
+module_LTLIBRARIES += \
+ $(ivi_shell)
+
+ivi_shell = ivi-shell.la
+ivi_shell_la_LDFLAGS = -module -avoid-version
+ivi_shell_la_LIBADD = $(COMPOSITOR_LIBS) $(IVI_SHELL_LIBS) libshared.la
+ivi_shell_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) $(IVI_SHELL_CFLAGS)
+ivi_shell_la_SOURCES = \
+ ivi-shell/ivi-shell.h \
+ ivi-shell/ivi-shell.c \
+ ivi-shell/ivi-layout.h
+nodist_ivi_shell_la_SOURCES = \
+ protocol/ivi-application-protocol.c \
+ protocol/ivi-application-server-protocol.h
+
+BUILT_SOURCES += $(nodist_ivi_shell_la_SOURCES)
+
+endif
+
+
if ENABLE_SCREEN_SHARING

module_LTLIBRARIES += screen-share.la
diff --git a/configure.ac b/configure.ac
index 031a26f..23e6ba5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -433,6 +433,16 @@ if test "x$enable_dbus" != "xno"; then
fi
AM_CONDITIONAL(ENABLE_DBUS, test "x$enable_dbus" = "xyes")

+# ivi-shell support
+AC_ARG_ENABLE(ivi-shell,
+ AS_HELP_STRING([--disable-ivi-shell],
+ [do not build ivi-shell server plugin and client]),,
+ enable_ivi_shell=yes)
+AM_CONDITIONAL(ENABLE_IVI_SHELL, test "x$enable_ivi_shell" = "xyes")
+if test x$enable_ivi_shell = xyes; then
+ PKG_CHECK_MODULES(IVI_SHELL, [cairo])
+fi
+
AC_ARG_ENABLE(wcap-tools, [ --disable-wcap-tools],, enable_wcap_tools=yes)
AM_CONDITIONAL(BUILD_WCAP_TOOLS, test x$enable_wcap_tools = xyes)
if test x$enable_wcap_tools = xyes; then
@@ -522,6 +532,8 @@ AC_MSG_RESULT([
XWayland ${enable_xwayland}
dbus ${enable_dbus}

+ ivi-shell ${enable_ivi_shell}
+
Build wcap utility ${enable_wcap_tools}
Build Fullscreen Shell ${enable_fullscreen_shell}

diff --git a/ivi-shell/ivi-layout.h b/ivi-shell/ivi-layout.h
new file mode 100644
index 0000000..a949b4c
--- /dev/null
+++ b/ivi-shell/ivi-layout.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * The ivi-layout library supports API set of controlling properties of
+ * surface and layer which groups surfaces. An unique ID whose type is integer
+ * is required to create surface and layer. With the unique ID, surface and
+ * layer are identified to control them. The API set consists of APIs to control
+ * properties of surface and layers about followings,
+ * - visibility.
+ * - opacity.
+ * - clipping (x,y,width,height).
+ * - position and size of it to be displayed.
+ * - orientation per 90 degree.
+ * - add or remove surfaces to a layer.
+ * - order of surfaces/layers in layer/screen to be displayed.
+ * - commit to apply property changes.
+ * - notifications of property change.
+ *
+ * Management of surfaces and layers grouping these surfaces are common way in
+ * In-Vehicle Infotainment system, which integrate several domains in one system.
+ * A layer is allocated to a domain in order to control application surfaces
+ * grouped to the layer all together.
+ */
+
+#ifndef _IVI_LAYOUT_H_
+#define _IVI_LAYOUT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "compositor.h"
+
+struct ivi_layout_surface;
+
+struct ivi_layout_interface {
+ struct weston_view* (*get_weston_view)(struct ivi_layout_surface *surface);
+ void (*surfaceConfigure)(struct ivi_layout_surface *ivisurf,
+ uint32_t width, uint32_t height);
+ int32_t (*surfaceSetNativeContent)(struct weston_surface *wl_surface,
+ uint32_t width,
+ uint32_t height,
+ uint32_t id_surface);
+ struct ivi_layout_surface* (*surfaceCreate)(struct weston_surface *wl_surface,
+ uint32_t id_surface);
+ void (*initWithCompositor)(struct weston_compositor *ec);
+};
+
+WL_EXPORT struct ivi_layout_interface ivi_layout_interface;
+
+#ifdef __cplusplus
+} /**/
+#endif /* __cplusplus */
+
+#endif /* _IVI_LAYOUT_H_ */
diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c
new file mode 100644
index 0000000..13bb1ed
--- /dev/null
+++ b/ivi-shell/ivi-shell.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+/**
+ * ivi-shell supports a type of shell for In-Vehicle Infotainment system.
+ * In-Vehicle Infotainment system traditionally manages surfaces with global
+ * identification. A protocol, ivi_application, supports such a feature
+ * by implementing a request, ivi_application::surface_creation defined in
+ * ivi_application.xml.
+ *
+ * The ivi-shell explicitly loads a module to add business logic like how to
+ * layout surfaces by using internal ivi-layout APIs.
+ */
+#include "config.h"
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+#include <dlfcn.h>
+#include <limits.h>
+
+#include "ivi-shell.h"
+#include "ivi-application-server-protocol.h"
+#include "ivi-layout.h"
+
+#include "../shared/os-compatibility.h"
+
+struct ivi_shell_surface
+{
+ struct ivi_shell *shell;
+ struct ivi_layout_surface *layout_surface;
+
+ struct weston_surface *surface;
+ uint32_t id_surface;
+
+ int32_t width;
+ int32_t height;
+
+ struct wl_list link;
+};
+
+struct ivi_shell_setting
+{
+ char *ivi_module;
+};
+
+static struct ivi_layout_interface *ivi_layout;
+
+/* ------------------------------------------------------------------------- */
+
+ /* common functions */
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Implementation of ivi_surface
+ */
+
+static void
+ivi_shell_surface_configure(struct weston_surface *, int32_t, int32_t);
+
+static struct ivi_shell_surface *
+get_ivi_shell_surface(struct weston_surface *surface)
+{
+ if (surface->configure == ivi_shell_surface_configure) {
+ return surface->configure_private;
+ } else {
+ return NULL;
+ }
+}
+
+static void
+ivi_shell_surface_configure(struct weston_surface *surface,
+ int32_t sx, int32_t sy)
+{
+ struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(surface);
+ struct weston_view *view = NULL;
+ float from_x = 0.0f;
+ float from_y = 0.0f;
+ float to_x = 0.0f;
+ float to_y = 0.0f;
+
+ if ((surface->width == 0) || (surface->height == 0) || (ivisurf == NULL)) {
+ return;
+ }
+
+ view = ivi_layout->get_weston_view(ivisurf->layout_surface);
+ if (view == NULL) {
+ return;
+ }
+
+ if (ivisurf->width != surface->width || ivisurf->height != surface->height) {
+
+ ivisurf->width = surface->width;
+ ivisurf->height = surface->height;
+
+ weston_view_to_global_float(view, 0, 0, &from_x, &from_y);
+ weston_view_to_global_float(view, sx, sy, &to_x, &to_y);
+
+ weston_view_set_position(view,
+ view->geometry.x + to_x - from_x,
+ view->geometry.y + to_y - from_y);
+ weston_view_update_transform(view);
+
+ ivi_layout->surfaceConfigure(ivisurf->layout_surface, surface->width, surface->height);
+ }
+}
+
+static void
+surface_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ struct ivi_shell_surface *ivisurf = wl_resource_get_user_data(resource);
+
+ if (ivisurf != NULL) {
+ ivisurf->surface->configure = NULL;
+ ivisurf->surface->configure_private = NULL;
+ ivisurf->surface = NULL;
+ ivi_layout->surfaceSetNativeContent(NULL, 0, 0, ivisurf->id_surface);
+ }
+
+ wl_resource_destroy(resource);
+}
+
+static const struct ivi_surface_interface surface_implementation = {
+ surface_destroy,
+};
+
+static struct ivi_shell_surface *
+is_surf_in_surfaces(struct wl_list *list_surf, uint32_t id_surface)
+{
+ struct ivi_shell_surface *ivisurf;
+
+ wl_list_for_each(ivisurf, list_surf, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+static const struct {
+ uint32_t warning_code; /* enum ivi_surface_warning_code */
+ const char *msg;
+} warning_strings[] = {
+ {IVI_SURFACE_WARNING_CODE_INVALID_WL_SURFACE, "wl_surface is invalid"},
+ {IVI_SURFACE_WARNING_CODE_IVI_ID_IN_USE, "surface_id is already assigned by another app"}
+};
+
+/**
+ * Implementation of ivi_application::surface_create.
+ * Creating new ivi_shell_surface with identification to identify the surface
+ * in the system.
+ */
+static void
+application_surface_create(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id_surface,
+ struct wl_resource *surface_resource,
+ uint32_t id)
+{
+ struct ivi_shell *shell = wl_resource_get_user_data(resource);
+ struct ivi_shell_surface *ivisurf = NULL;
+ struct ivi_layout_surface *layout_surface = NULL;
+ struct weston_surface *weston_surface = wl_resource_get_user_data(surface_resource);
+ struct wl_resource *res;
+ int32_t warn_idx = -1;
+
+ if (weston_surface != NULL) {
+
+ /* check if a surface already has another role*/
+ if (weston_surface->configure) {
+ wl_resource_post_error(weston_surface->resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "surface->configure already "
+ "set");
+ return;
+ }
+
+ layout_surface = ivi_layout->surfaceCreate(weston_surface, id_surface);
+
+ if (layout_surface == NULL)
+ warn_idx = 1;
+ } else {
+ warn_idx = 0;
+ }
+
+ res = wl_resource_create(client, &ivi_surface_interface, 1, id);
+ if (res == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ if (warn_idx >= 0) {
+ wl_resource_set_implementation(res, &surface_implementation,
+ NULL, NULL);
+ ivi_surface_send_warning(res,
+ warning_strings[warn_idx].warning_code,
+ warning_strings[warn_idx].msg);
+ return;
+ }
+
+ ivisurf = is_surf_in_surfaces(&shell->ivi_surface_list, id_surface);
+ if (ivisurf == NULL) {
+ ivisurf = zalloc(sizeof *ivisurf);
+ if (ivisurf == NULL) {
+ wl_resource_post_no_memory(res);
+ return;
+ }
+
+ wl_list_init(&ivisurf->link);
+ wl_list_insert(&shell->ivi_surface_list, &ivisurf->link);
+
+ ivisurf->shell = shell;
+ ivisurf->id_surface = id_surface;
+ }
+
+ ivisurf->width = 0;
+ ivisurf->height = 0;
+ ivisurf->layout_surface = layout_surface;
+ ivisurf->surface = weston_surface;
+
+ weston_surface->configure = ivi_shell_surface_configure;
+ weston_surface->configure_private = ivisurf;
+
+ wl_resource_set_implementation(res, &surface_implementation,
+ ivisurf, NULL);
+}
+
+static const struct ivi_application_interface application_implementation = {
+ application_surface_create
+};
+
+static void
+bind_ivi_application(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct ivi_shell *shell = data;
+ struct wl_resource *resource = NULL;
+
+ resource = wl_resource_create(client, &ivi_application_interface, 1, id);
+
+ wl_resource_set_implementation(resource,
+ &application_implementation,
+ shell, NULL);
+}
+
+/**
+ * Initialization/destruction method of ivi-shell
+ */
+static void
+shell_destroy(struct wl_listener *listener, void *data)
+{
+ struct ivi_shell *shell =
+ container_of(listener, struct ivi_shell, destroy_listener);
+ struct ivi_shell_surface *ivisurf, *next;
+
+ wl_list_for_each_safe(ivisurf, next, &shell->ivi_surface_list, link) {
+ wl_list_remove(&ivisurf->link);
+ free(ivisurf);
+ }
+
+ free(shell);
+}
+
+static void
+init_ivi_shell(struct weston_compositor *compositor, struct ivi_shell *shell)
+{
+ shell->compositor = compositor;
+
+ wl_list_init(&shell->ivi_surface_list);
+}
+
+static int
+ivi_shell_setting_create(struct ivi_shell_setting *dest)
+{
+ int result = 0;
+ struct weston_config *config = NULL;
+ struct weston_config_section *section = NULL;
+
+ if (NULL == dest) {
+ return -1;
+ }
+
+ config = weston_config_parse("weston.ini");
+ section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
+
+ if (weston_config_section_get_string(
+ section, "ivi-module", (char **)&dest->ivi_module, NULL) != 0)
+ {
+ result = -1;
+ }
+
+ weston_config_destroy(config);
+ return result;
+}
+
+/**
+ * Initialization of ivi-shell.
+ */
+static int
+ivi_load_modules(struct weston_compositor *compositor, const char *modules,
+ int *argc, char *argv[])
+{
+ const char *p, *end;
+ char buffer[256];
+ int (*module_init)(struct weston_compositor *compositor,
+ int *argc, char *argv[]);
+
+ if (modules == NULL)
+ return 0;
+
+ p = modules;
+ while (*p) {
+ end = strchrnul(p, ',');
+ snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
+ module_init = weston_load_module(buffer, "module_init");
+ if (module_init)
+ module_init(compositor, argc, argv);
+ p = end;
+ while (*p == ',')
+ p++;
+
+ }
+
+ return 0;
+}
+
+WL_EXPORT int
+module_init(struct weston_compositor *compositor,
+ int *argc, char *argv[])
+{
+ struct ivi_shell *shell = NULL;
+ char ivi_layout_path[PATH_MAX];
+ void *module;
+ struct ivi_shell_setting setting = { };
+
+ shell = zalloc(sizeof *shell);
+ if (shell == NULL) {
+ return -1;
+ }
+
+ init_ivi_shell(compositor, shell);
+
+ shell->destroy_listener.notify = shell_destroy;
+ wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener);
+
+ if (wl_global_create(compositor->wl_display, &ivi_application_interface, 1,
+ shell, bind_ivi_application) == NULL) {
+ return -1;
+ }
+
+ if (ivi_shell_setting_create(&setting) != 0) {
+ return 0;
+ }
+
+ /*load module:ivi-layout*/
+ /*ivi_layout_interface is referred by ivi-shell to use ivi-layout*/
+ snprintf(ivi_layout_path, sizeof ivi_layout_path, "%s/%s", MODULEDIR, "ivi-layout.so");
+ module = dlopen(ivi_layout_path, RTLD_NOW | RTLD_NOLOAD);
+ if (module) {
+ weston_log("ivi-shell: Module '%s' already loaded\n", ivi_layout_path);
+ dlclose(module);
+ return -1;
+ }
+
+ weston_log("ivi-shell: Loading module '%s'\n", ivi_layout_path);
+ module = dlopen(ivi_layout_path, RTLD_NOW | RTLD_GLOBAL);
+ if (!module) {
+ weston_log("ivi-shell: Failed to load module: %s\n", dlerror());
+ return -1;
+ }
+
+ ivi_layout = dlsym(module,"ivi_layout_interface");
+ if (!ivi_layout){
+ weston_log("ivi-shell: couldn't find ivi_layout_interface in '%s'\n", ivi_layout_path);
+ free(setting.ivi_module);
+ return -1;
+ }
+ else{
+ ivi_layout->initWithCompositor(compositor);
+ }
+
+ /*Call module_init of ivi-modules which are defined in weston.ini*/
+ if (ivi_load_modules(compositor,setting.ivi_module,argc,argv) < 0){
+ free(setting.ivi_module);
+ return -1;
+ }
+
+ free(setting.ivi_module);
+ return 0;
+}
diff --git a/ivi-shell/ivi-shell.h b/ivi-shell/ivi-shell.h
new file mode 100644
index 0000000..157c5ae
--- /dev/null
+++ b/ivi-shell/ivi-shell.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdbool.h>
+
+#include "compositor.h"
+
+struct ivi_shell
+{
+ struct wl_resource *resource;
+ struct wl_listener destroy_listener;
+
+ struct weston_compositor *compositor;
+
+ struct wl_list ivi_surface_list; /* struct ivi_shell_surface::link */
+};
--
1.8.3.1
Nobuhiko Tanibata
2014-05-20 04:29:14 UTC
Permalink
API set of controlling properties of surface and layer which groups
surfaces. An unique ID whose type is integer is required to create
surface and layer. With the unique ID, surface and layer are identified
to control them. The API set consists of APIs to control properties of
surface and layers about followings,

- visibility.
- opacity.
- clipping (x,y,width,height).
- position and size of it to be displayed.
- orientation per 90 degree.
- add or remove surfaces to a layer.
- order of surfaces/layers in layer/screen to be displayed.
- commit to apply property changes.
- notifications of property change.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- move this patch in front of ivi-shell patch to be compiled successfully.
- unsupport weston_layout_takeSurfaceScreenshot because implementation needs to
be discussed more. It is pending.
- support inherit propoerties of id_surface when client attaches another
wl_surface with id_surface after destroying ivi_surface once.
- bug fix of https://bugs.tizen.org/jira/browse/TIVI-2882

Changes for v3 and v4
- nothing. Version number aligned to the first patch

Changes for v5:
- rebase weston v1.5 branch
- apply review comments from mailing list

Makefile.am | 17 +-
ivi-shell/ivi-layout-export.h | 964 ++++++++++++++
ivi-shell/ivi-layout.c | 2798 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 3778 insertions(+), 1 deletion(-)
create mode 100644 ivi-shell/ivi-layout-export.h
create mode 100644 ivi-shell/ivi-layout.c

diff --git a/Makefile.am b/Makefile.am
index 279fffc..e8bcb1b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -703,7 +703,8 @@ endif
if ENABLE_IVI_SHELL

module_LTLIBRARIES += \
- $(ivi_shell)
+ $(ivi_shell) \
+ $(ivi_layout)

ivi_shell = ivi-shell.la
ivi_shell_la_LDFLAGS = -module -avoid-version
@@ -719,6 +720,20 @@ nodist_ivi_shell_la_SOURCES = \

BUILT_SOURCES += $(nodist_ivi_shell_la_SOURCES)

+ivi_layout = ivi-layout.la
+ivi_layout_la_LDFLAGS = -module -avoid-version
+ivi_layout_la_LIBADD = $(COMPOSITOR_LIBS) $(IVI_SHELL_LIBS) libshared.la
+ivi_layout_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) $(IVI_SHELL_CFLAGS)
+ivi_layout_la_SOURCES = \
+ ivi-shell/ivi-layout.h \
+ ivi-shell/ivi-layout-export.h \
+ ivi-shell/ivi-layout.c
+nodist_ivi_layout_la_SOURCES = \
+ protocol/ivi-application-protocol.c \
+ protocol/ivi-application-server-protocol.h
+
+BUILT_SOURCES += $(nodist_ivi_layout_la_SOURCES)
+
endif


diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h
new file mode 100644
index 0000000..0f95f53
--- /dev/null
+++ b/ivi-shell/ivi-layout-export.h
@@ -0,0 +1,964 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * The ivi-layout library supports API set of controlling properties of
+ * surface and layer which groups surfaces. An unique ID whose type is integer
+ * is required to create surface and layer. With the unique ID, surface and
+ * layer are identified to control them. The API set consists of APIs to control
+ * properties of surface and layers about followings,
+ * - visibility.
+ * - opacity.
+ * - clipping (x,y,width,height).
+ * - position and size of it to be displayed.
+ * - orientation per 90 degree.
+ * - add or remove surfaces to a layer.
+ * - order of surfaces/layers in layer/screen to be displayed.
+ * - commit to apply property changes.
+ * - notifications of property change.
+ *
+ * Management of surfaces and layers grouping these surfaces are common way in
+ * In-Vehicle Infotainment system, which integrate several domains in one system.
+ * A layer is allocated to a domain in order to control application surfaces
+ * grouped to the layer all together.
+ */
+
+#ifndef _IVI_LAYOUT_EXPORT_H_
+#define _IVI_LAYOUT_EXPORT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "compositor.h"
+#include "ivi-layout.h"
+
+struct ivi_layout_SurfaceProperties
+{
+ float opacity;
+ uint32_t sourceX;
+ uint32_t sourceY;
+ uint32_t sourceWidth;
+ uint32_t sourceHeight;
+ uint32_t origSourceWidth;
+ uint32_t origSourceHeight;
+ int32_t destX;
+ int32_t destY;
+ uint32_t destWidth;
+ uint32_t destHeight;
+ uint32_t orientation;
+ uint32_t visibility;
+ uint32_t frameCounter;
+ uint32_t drawCounter;
+ uint32_t updateCounter;
+ uint32_t pixelformat;
+ uint32_t nativeSurface;
+ uint32_t inputDevicesAcceptance;
+ uint32_t chromaKeyEnabled;
+ uint32_t chromaKeyRed;
+ uint32_t chromaKeyGreen;
+ uint32_t chromaKeyBlue;
+ int32_t creatorPid;
+};
+
+struct ivi_layout_LayerProperties
+{
+ float opacity;
+ uint32_t sourceX;
+ uint32_t sourceY;
+ uint32_t sourceWidth;
+ uint32_t sourceHeight;
+ uint32_t origSourceWidth;
+ uint32_t origSourceHeight;
+ int32_t destX;
+ int32_t destY;
+ uint32_t destWidth;
+ uint32_t destHeight;
+ uint32_t orientation;
+ uint32_t visibility;
+ uint32_t type;
+ uint32_t chromaKeyEnabled;
+ uint32_t chromaKeyRed;
+ uint32_t chromaKeyGreen;
+ uint32_t chromaKeyBlue;
+ int32_t creatorPid;
+};
+
+struct ivi_layout_layer;
+struct ivi_layout_screen;
+
+typedef struct ivi_layout_surface* ivi_layout_surface_ptr;
+typedef struct ivi_layout_layer* ivi_layout_layer_ptr;
+typedef struct ivi_layout_screen* ivi_layout_screen_ptr;
+
+enum ivi_layout_notification_mask {
+ IVI_NOTIFICATION_NONE = 0,
+ IVI_NOTIFICATION_OPACITY = (1 << 1),
+ IVI_NOTIFICATION_SOURCE_RECT = (1 << 2),
+ IVI_NOTIFICATION_DEST_RECT = (1 << 3),
+ IVI_NOTIFICATION_DIMENSION = (1 << 4),
+ IVI_NOTIFICATION_POSITION = (1 << 5),
+ IVI_NOTIFICATION_ORIENTATION = (1 << 6),
+ IVI_NOTIFICATION_VISIBILITY = (1 << 7),
+ IVI_NOTIFICATION_PIXELFORMAT = (1 << 8),
+ IVI_NOTIFICATION_ADD = (1 << 9),
+ IVI_NOTIFICATION_REMOVE = (1 << 10),
+ IVI_NOTIFICATION_ALL = 0xFFFF
+};
+
+typedef void(*layerPropertyNotificationFunc)(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_LayerProperties*,
+ enum ivi_layout_notification_mask mask,
+ void *userdata);
+
+typedef void(*surfacePropertyNotificationFunc)(struct ivi_layout_surface *ivisurf,
+ struct ivi_layout_SurfaceProperties*,
+ enum ivi_layout_notification_mask mask,
+ void *userdata);
+
+typedef void(*layerCreateNotificationFunc)(struct ivi_layout_layer *ivilayer,
+ void *userdata);
+
+typedef void(*layerRemoveNotificationFunc)(struct ivi_layout_layer *ivilayer,
+ void *userdata);
+
+typedef void(*surfaceCreateNotificationFunc)(struct ivi_layout_surface *ivisurf,
+ void *userdata);
+
+typedef void(*surfaceRemoveNotificationFunc)(struct ivi_layout_surface *ivisurf,
+ void *userdata);
+
+typedef void(*surfaceConfigureNotificationFunc)(struct ivi_layout_surface *ivisurf,
+ void *userdata);
+
+/**
+ * \brief to be called by ivi-shell in order to set initail view of
+ * weston_surface.
+ */
+/*
+struct weston_view *
+ivi_layout_get_weston_view(struct ivi_layout_surface *surface);
+*/
+
+/**
+ * \brief initialize ivi-layout
+ */
+/*
+void
+ivi_layout_initWithCompositor(struct weston_compositor *ec);
+*/
+
+/**
+ * \brief register for notification when layer is created
+ */
+int32_t
+ivi_layout_addNotificationCreateLayer(layerCreateNotificationFunc callback,
+ void *userdata);
+
+void
+ivi_layout_removeNotificationCreateLayer(layerCreateNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when layer is removed
+ */
+int32_t
+ivi_layout_addNotificationRemoveLayer(layerRemoveNotificationFunc callback,
+ void *userdata);
+
+void
+ivi_layout_removeNotificationRemoveLayer(layerRemoveNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is created
+ */
+int32_t
+ivi_layout_addNotificationCreateSurface(surfaceCreateNotificationFunc callback,
+ void *userdata);
+
+void
+ivi_layout_removeNotificationCreateSurface(surfaceCreateNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is removed
+ */
+int32_t
+ivi_layout_addNotificationRemoveSurface(surfaceRemoveNotificationFunc callback,
+ void *userdata);
+
+void
+ivi_layout_removeNotificationRemoveSurface(surfaceRemoveNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief register for notification when surface is configured
+ */
+int32_t
+ivi_layout_addNotificationConfigureSurface(surfaceConfigureNotificationFunc callback,
+ void *userdata);
+
+void
+ivi_layout_removeNotificationConfigureSurface(surfaceConfigureNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief get id of surface from ivi_layout_surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+uint32_t
+ivi_layout_getIdOfSurface(struct ivi_layout_surface *ivisurf);
+
+/**
+ * \brief get id of layer from ivi_layout_layer
+ *
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+uint32_t
+ivi_layout_getIdOfLayer(struct ivi_layout_layer *ivilayer);
+
+/**
+ * \brief get ivi_layout_layer from id of layer
+ *
+ * \return (struct ivi_layout_layer *)
+ * if the method call was successful
+ * \return NULL if the method call was failed
+ */
+struct ivi_layout_layer *
+ivi_layout_getLayerFromId(uint32_t id_layer);
+
+/**
+ * \brief get ivi_layout_surface from id of surface
+ *
+ * \return (struct ivi_layout_surface *)
+ * if the method call was successful
+ * \return NULL if the method call was failed
+ */
+struct ivi_layout_surface *
+ivi_layout_getSurfaceFromId(uint32_t id_surface);
+
+/**
+ * \brief get ivi_layout_screen from id of screen
+ *
+ * \return (struct ivi_layout_screen *)
+ * if the method call was successful
+ * \return NULL if the method call was failed
+ */
+struct ivi_layout_screen *
+ivi_layout_getScreenFromId(uint32_t id_screen);
+
+/**
+ * \brief Get the screen resolution of a specific screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getScreenResolution(struct ivi_layout_screen *iviscrn,
+ uint32_t *pWidth,
+ uint32_t *pHeight);
+
+/**
+ * \brief register for notification on property changes of surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceAddNotification(struct ivi_layout_surface *ivisurf,
+ surfacePropertyNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief remove notification on property changes of surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceRemoveNotification(struct ivi_layout_surface *ivisurf);
+
+/**
+ * \brief Create a surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+/*
+struct ivi_layout_surface *
+ivi_layout_surfaceCreate(struct weston_surface *wl_surface,
+ uint32_t id_surface);
+*/
+
+/**
+ * \brief Set the native content of an application to be used as surface content.
+ * If wl_surface is NULL, remove the native content of a surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+/*
+int32_t
+ivi_layout_surfaceSetNativeContent(struct weston_surface *wl_surface,
+ uint32_t width,
+ uint32_t height,
+ uint32_t id_surface);
+*/
+
+/**
+ * \brief initialize ivi_layout_surface dest/source width and height
+ */
+/*
+void
+ivi_layout_surfaceConfigure(struct ivi_layout_surface *ivisurf,
+ uint32_t width, uint32_t height);
+*/
+
+/**
+ * \brief Remove a surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceRemove(struct ivi_layout_surface *ivisurf);
+
+/**
+ * \brief Set from which kind of devices the surface can accept input events.
+ * By default, a surface accept input events from all kind of devices (keyboards, pointer, ...)
+ * By calling this function, you can adjust surface preferences. Note that this function only
+ * adjust the acceptance for the specified devices. Non specified are keept untouched.
+ *
+ * Typicall use case for this function is when dealing with pointer or touch events.
+ * Those are normally dispatched to the first visible surface below the coordinate.
+ * If you want a different behavior (i.e. forward events to an other surface below the coordinate,
+ * you can set all above surfaces to refuse input events)
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_UpdateInputEventAcceptanceOn(struct ivi_layout_surface *ivisurf,
+ uint32_t devices,
+ uint32_t acceptance);
+
+/**
+ * \brief Get the layer properties
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getPropertiesOfLayer(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_LayerProperties *pLayerProperties);
+
+/**
+ * \brief Get the number of hardware layers of a screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getNumberOfHardwareLayers(uint32_t id_screen,
+ uint32_t *pNumberOfHardwareLayers);
+
+/**
+ * \brief Get the screens
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getScreens(uint32_t *pLength, ivi_layout_screen_ptr **ppArray);
+
+/**
+ * \brief Get the screens under the given layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getScreensUnderLayer(struct ivi_layout_layer *ivilayer,
+ uint32_t *pLength,
+ ivi_layout_screen_ptr **ppArray);
+
+/**
+ * \brief Get all Layers which are currently registered and managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getLayers(uint32_t *pLength, ivi_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Layers of the given screen
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getLayersOnScreen(struct ivi_layout_screen *iviscrn,
+ uint32_t *pLength,
+ ivi_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Layers under the given surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getLayersUnderSurface(struct ivi_layout_surface *ivisurf,
+ uint32_t *pLength,
+ ivi_layout_layer_ptr **ppArray);
+
+/**
+ * \brief Get all Surfaces which are currently registered and managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getSurfaces(uint32_t *pLength, ivi_layout_surface_ptr **ppArray);
+
+/**
+ * \brief Get all Surfaces which are currently registered to a given layer and are managed by the services
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getSurfacesOnLayer(struct ivi_layout_layer *ivilayer,
+ uint32_t *pLength,
+ ivi_layout_surface_ptr **ppArray);
+
+/**
+ * \brief Create a layer which should be managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+struct ivi_layout_layer *
+ivi_layout_layerCreateWithDimension(uint32_t id_layer,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Removes a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerRemove(struct ivi_layout_layer *ivilayer);
+
+/**
+ * \brief Get the current type of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerGetType(struct ivi_layout_layer *ivilayer,
+ uint32_t *pLayerType);
+
+/**
+ * \brief Set the visibility of a layer. If a layer is not visible, the layer and its
+ * surfaces will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetVisibility(struct ivi_layout_layer *ivilayer,
+ uint32_t newVisibility);
+
+/**
+ * \brief Get the visibility of a layer. If a layer is not visible, the layer and its
+ * surfaces will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerGetVisibility(struct ivi_layout_layer *ivilayer,
+ uint32_t *pVisibility);
+
+/**
+ * \brief Set the opacity of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetOpacity(struct ivi_layout_layer *ivilayer, float opacity);
+
+/**
+ * \brief Get the opacity of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerGetOpacity(struct ivi_layout_layer *ivilayer, float *pOpacity);
+
+/**
+ * \brief Set the area of a layer which should be used for the rendering.
+ * Only this part will be visible.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetSourceRectangle(struct ivi_layout_layer *ivilayer,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Set the destination area on the display for a layer.
+ * The layer will be scaled and positioned to this rectangle for rendering
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetDestinationRectangle(struct ivi_layout_layer *ivilayer,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Get the horizontal and vertical dimension of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerGetDimension(struct ivi_layout_layer *ivilayer,
+ uint32_t *pDimension);
+
+/**
+ * \brief Set the horizontal and vertical dimension of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetDimension(struct ivi_layout_layer *ivilayer,
+ uint32_t *pDimension);
+
+/**
+ * \brief Get the horizontal and vertical position of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerGetPosition(struct ivi_layout_layer *ivilayer,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the horizontal and vertical position of the layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetPosition(struct ivi_layout_layer *ivilayer,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the orientation of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetOrientation(struct ivi_layout_layer *ivilayer,
+ uint32_t orientation);
+
+/**
+ * \brief Gets the orientation of a layer.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerGetOrientation(struct ivi_layout_layer *ivilayer,
+ uint32_t *pOrientation);
+
+/**
+ * \brief Sets the color value which defines the transparency value.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetChromaKey(struct ivi_layout_layer *ivilayer,
+ uint32_t* pColor);
+
+/**
+ * \brief Sets render order of surfaces within one layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerSetRenderOrder(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface **pSurface,
+ uint32_t number);
+
+/**
+ * \brief Get the capabilities of a layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerGetCapabilities(struct ivi_layout_layer *ivilayer,
+ uint32_t *pCapabilities);
+
+/**
+ * \brief Get the possible capabilities of a layertype
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerTypeGetCapabilities(uint32_t layerType,
+ uint32_t *pCapabilities);
+
+/**
+ * \brief Create the logical surface, which has no native buffer associated
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceInitialize(struct ivi_layout_surface **pSurface);
+
+/**
+ * \brief Set the visibility of a surface.
+ * If a surface is not visible it will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceSetVisibility(struct ivi_layout_surface *ivisurf,
+ uint32_t newVisibility);
+
+/**
+ * \brief Get the visibility of a surface.
+ * If a surface is not visible it will not be rendered.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceGetVisibility(struct ivi_layout_surface *ivisurf,
+ uint32_t *pVisibility);
+
+/**
+ * \brief Set the opacity of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceSetOpacity(struct ivi_layout_surface *ivisurf,
+ float opacity);
+
+/**
+ * \brief Get the opacity of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceGetOpacity(struct ivi_layout_surface *ivisurf,
+ float *pOpacity);
+
+/**
+ * \brief Set the keyboard focus on a certain surface
+ * To receive keyboard events, 2 conditions must be fulfilled:
+ * 1- The surface must accept events from keyboard. See ilm_UpdateInputEventAcceptanceOn
+ * 2- The keyboard focus must be set on that surface
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_SetKeyboardFocusOn(struct ivi_layout_surface *ivisurf);
+
+/**
+ * \brief Get the indentifier of the surface which hold the keyboard focus
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_GetKeyboardFocusSurfaceId(struct ivi_layout_surface **pSurfaceId);
+
+/**
+ * \brief Set the destination area of a surface within a layer for rendering.
+ * The surface will be scaled to this rectangle for rendering.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceSetDestinationRectangle(struct ivi_layout_surface *ivisurf,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Set the horizontal and vertical dimension of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceSetDimension(struct ivi_layout_surface *ivisurf,
+ uint32_t *pDimension);
+
+/**
+ * \brief Get the horizontal and vertical dimension of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceGetDimension(struct ivi_layout_surface *ivisurf,
+ uint32_t *pDimension);
+
+/**
+ * \brief Sets the horizontal and vertical position of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceSetPosition(struct ivi_layout_surface *ivisurf,
+ int32_t *pPosition);
+
+/**
+ * \brief Get the horizontal and vertical position of the surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceGetPosition(struct ivi_layout_surface *ivisurf,
+ int32_t *pPosition);
+
+/**
+ * \brief Sets the orientation of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceSetOrientation(struct ivi_layout_surface *ivisurf,
+ uint32_t orientation);
+
+/**
+ * \brief Gets the orientation of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceGetOrientation(struct ivi_layout_surface *ivisurf,
+ uint32_t *pOrientation);
+
+/**
+ * \brief Gets the pixelformat of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceGetPixelformat(struct ivi_layout_layer *ivisurf,
+ uint32_t *pPixelformat);
+
+/**
+ * \brief Sets the color value which defines the transparency value of a surface.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceSetChromaKey(struct ivi_layout_surface *ivisurf,
+ uint32_t* pColor);
+
+/**
+ * \brief Add a layer to a screen which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_screenAddLayer(struct ivi_layout_screen *iviscrn,
+ struct ivi_layout_layer *addlayer);
+
+/**
+ * \brief Sets render order of layers on a display
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_screenSetRenderOrder(struct ivi_layout_screen *iviscrn,
+ struct ivi_layout_layer **pLayer,
+ const uint32_t number);
+
+/**
+ * \brief Take a screenshot from the current displayed layer scene.
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_takeScreenshot(struct ivi_layout_screen *iviscrn,
+ const char *filename);
+
+/**
+ * \brief Take a screenshot of a certain layer
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_takeLayerScreenshot(const char *filename,
+ struct ivi_layout_layer *ivilayer);
+
+/**
+ * \brief Take a screenshot of a certain surface
+ * The screenshot is saved as bmp file with the corresponding filename.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_takeSurfaceScreenshot(const char *filename,
+ struct ivi_layout_surface *ivisurf);
+
+/**
+ * \brief Enable or disable a rendering optimization
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_SetOptimizationMode(uint32_t id, uint32_t mode);
+
+/**
+ * \brief Get the current enablement for an optimization
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_GetOptimizationMode(uint32_t id, uint32_t *pMode);
+
+/**
+ * \brief register for notification on property changes of layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerAddNotification(struct ivi_layout_layer *ivilayer,
+ layerPropertyNotificationFunc callback,
+ void *userdata);
+
+/**
+ * \brief remove notification on property changes of layer
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerRemoveNotification(struct ivi_layout_layer *ivilayer);
+
+/**
+ * \brief Get the surface properties
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_getPropertiesOfSurface(struct ivi_layout_surface *ivisurf,
+ struct ivi_layout_SurfaceProperties *pSurfaceProperties);
+
+/**
+ * \brief Add a surface to a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerAddSurface(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *addsurf);
+
+/**
+ * \brief Removes a surface from a layer which is currently managed by the service
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_layerRemoveSurface(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *remsurf);
+
+/**
+ * \brief Set the area of a surface which should be used for the rendering.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_surfaceSetSourceRectangle(struct ivi_layout_surface *ivisurf,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height);
+
+/**
+ * \brief Commit all changes and execute all enqueued commands since last commit.
+ *
+ * \return 0 if the method call was successful
+ * \return -1 if the method call was failed
+ */
+int32_t
+ivi_layout_commitChanges(void);
+
+#ifdef __cplusplus
+} /**/
+#endif /* __cplusplus */
+
+#endif /* _IVI_LAYOUT_EXPORT_H_ */
diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c
new file mode 100644
index 0000000..68f9b52
--- /dev/null
+++ b/ivi-shell/ivi-layout.c
@@ -0,0 +1,2798 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * Implementation of ivi-layout library. The actual view on screen is
+ * not updated till calling ivi_layout_commitChanges. A overview from
+ * calling API for updating properties of surfaces/layer to asking compositor
+ * to compose them by using weston_compositor_schedule_repaint,
+ * 0/ initialize this library by ivi_layout_initWithCompositor
+ * with (struct weston_compositor *ec) from ivi-shell.
+ * 1/ When a API for updating properties of surface/layer, it updates
+ * pending prop of ivi_layout_surface/layer/screen which are structure to
+ * store properties.
+ * 2/ Before calling commitChanges, in case of calling a API to get a property,
+ * return current property, not pending property.
+ * 3/ At the timing of calling ivi_layout_commitChanges, pending properties
+ * are applied
+ * to properties.
+ * 4/ According properties, set transformation by using weston_matrix and
+ * weston_view per surfaces and layers in while loop.
+ * 5/ Set damage and trigger transform by using weston_view_geometry_dirty and
+ * weston_view_geometry_dirty.
+ * 6/ Notify update of properties.
+ * 7/ Trigger composition by weston_compositor_schedule_repaint.
+ *
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+#include <cairo.h>
+
+#include "compositor.h"
+#include "ivi-layout.h"
+#include "ivi-layout-export.h"
+
+enum ivi_layout_surface_orientation {
+ IVI_LAYOUT_SURFACE_ORIENTATION_0_DEGREES = 0,
+ IVI_LAYOUT_SURFACE_ORIENTATION_90_DEGREES = 1,
+ IVI_LAYOUT_SURFACE_ORIENTATION_180_DEGREES = 2,
+ IVI_LAYOUT_SURFACE_ORIENTATION_270_DEGREES = 3,
+};
+
+enum ivi_layout_surface_pixelformat {
+ IVI_LAYOUT_SURFACE_PIXELFORMAT_R_8 = 0,
+ IVI_LAYOUT_SURFACE_PIXELFORMAT_RGB_888 = 1,
+ IVI_LAYOUT_SURFACE_PIXELFORMAT_RGBA_8888 = 2,
+ IVI_LAYOUT_SURFACE_PIXELFORMAT_RGB_565 = 3,
+ IVI_LAYOUT_SURFACE_PIXELFORMAT_RGBA_5551 = 4,
+ IVI_LAYOUT_SURFACE_PIXELFORMAT_RGBA_6661 = 5,
+ IVI_LAYOUT_SURFACE_PIXELFORMAT_RGBA_4444 = 6,
+ IVI_LAYOUT_SURFACE_PIXELFORMAT_UNKNOWN = 7,
+};
+
+struct link_layer {
+ struct ivi_layout_layer *ivilayer;
+ struct wl_list link;
+ struct wl_list link_to_layer;
+};
+
+struct link_screen {
+ struct ivi_layout_screen *iviscrn;
+ struct wl_list link;
+ struct wl_list link_to_screen;
+};
+
+struct link_layerPropertyNotification {
+ layerPropertyNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfacePropertyNotification {
+ surfacePropertyNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_layerCreateNotification {
+ layerCreateNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_layerRemoveNotification {
+ layerRemoveNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceCreateNotification {
+ surfaceCreateNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceRemoveNotification {
+ surfaceRemoveNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct link_surfaceConfigureNotification {
+ surfaceConfigureNotificationFunc callback;
+ void *userdata;
+ struct wl_list link;
+};
+
+struct ivi_layout;
+
+struct ivi_layout_surface {
+ struct wl_list link;
+ struct wl_list list_notification;
+ struct wl_list list_layer;
+ uint32_t update_count;
+ uint32_t id_surface;
+
+ struct ivi_layout *layout;
+ struct weston_surface *surface;
+ struct weston_view *view;
+
+ uint32_t buffer_width;
+ uint32_t buffer_height;
+
+ struct wl_listener surface_destroy_listener;
+ struct weston_transform surface_rotation;
+ struct weston_transform layer_rotation;
+ struct weston_transform surface_pos;
+ struct weston_transform layer_pos;
+ struct weston_transform scaling;
+ struct ivi_layout_SurfaceProperties prop;
+ int32_t pixelformat;
+ uint32_t event_mask;
+
+ struct {
+ struct ivi_layout_SurfaceProperties prop;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list link;
+ struct wl_list list_layer;
+ } order;
+};
+
+struct ivi_layout_layer {
+ struct wl_list link;
+ struct wl_list list_notification;
+ struct wl_list list_screen;
+ struct wl_list link_to_surface;
+ uint32_t id_layer;
+
+ struct ivi_layout *layout;
+
+ struct ivi_layout_LayerProperties prop;
+ uint32_t event_mask;
+
+ struct {
+ struct ivi_layout_LayerProperties prop;
+ struct wl_list list_surface;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list list_surface;
+ struct wl_list link;
+ } order;
+};
+
+struct ivi_layout_screen {
+ struct wl_list link;
+ struct wl_list link_to_layer;
+ uint32_t id_screen;
+
+ struct ivi_layout *layout;
+ struct weston_output *output;
+
+ uint32_t event_mask;
+
+ struct {
+ struct wl_list list_layer;
+ struct wl_list link;
+ } pending;
+
+ struct {
+ struct wl_list list_layer;
+ struct wl_list link;
+ } order;
+};
+
+struct ivi_layout {
+ struct weston_compositor *compositor;
+
+ struct wl_list list_surface;
+ struct wl_list list_layer;
+ struct wl_list list_screen;
+
+ struct {
+ struct wl_list list_create;
+ struct wl_list list_remove;
+ } layer_notification;
+
+ struct {
+ struct wl_list list_create;
+ struct wl_list list_remove;
+ struct wl_list list_configure;
+ } surface_notification;
+
+ struct weston_layer layout_layer;
+};
+
+static struct ivi_layout ivilayout = {0};
+
+static struct ivi_layout *
+get_instance(void)
+{
+ return &ivilayout;
+}
+
+/**
+ * Internal API to add/remove a link to surface from layer.
+ */
+static void
+add_link_to_surface(struct ivi_layout_layer *ivilayer,
+ struct link_layer *link_layer)
+{
+ wl_list_init(&link_layer->link_to_layer);
+ wl_list_insert(&ivilayer->link_to_surface, &link_layer->link_to_layer);
+}
+
+static void
+remove_link_to_surface(struct ivi_layout_layer *ivilayer)
+{
+ struct link_layer *link = NULL;
+ struct link_layer *next = NULL;
+
+ wl_list_for_each_safe(link, next, &ivilayer->link_to_surface, link_to_layer) {
+ if (!wl_list_empty(&link->link_to_layer)) {
+ wl_list_remove(&link->link_to_layer);
+ }
+ free(link);
+ }
+
+ wl_list_init(&ivilayer->link_to_surface);
+}
+
+/**
+ * Internal API to add a link to layer from screen.
+ */
+static void
+add_link_to_layer(struct ivi_layout_screen *iviscrn,
+ struct link_screen *link_screen)
+{
+ wl_list_init(&link_screen->link_to_screen);
+ wl_list_insert(&iviscrn->link_to_layer, &link_screen->link_to_screen);
+}
+
+/**
+ * Internal API to add/remove a surface from layer.
+ */
+static void
+add_ordersurface_to_layer(struct ivi_layout_surface *ivisurf,
+ struct ivi_layout_layer *ivilayer)
+{
+ struct link_layer *link_layer = NULL;
+
+ link_layer = malloc(sizeof *link_layer);
+ if (link_layer == NULL) {
+ weston_log("fails to allocate memory\n");
+ return;
+ }
+
+ link_layer->ivilayer = ivilayer;
+ wl_list_init(&link_layer->link);
+ wl_list_insert(&ivisurf->list_layer, &link_layer->link);
+ add_link_to_surface(ivilayer, link_layer);
+}
+
+static void
+remove_ordersurface_from_layer(struct ivi_layout_surface *ivisurf)
+{
+ struct link_layer *link_layer = NULL;
+ struct link_layer *next = NULL;
+
+ wl_list_for_each_safe(link_layer, next, &ivisurf->list_layer, link) {
+ if (!wl_list_empty(&link_layer->link)) {
+ wl_list_remove(&link_layer->link);
+ }
+ free(link_layer);
+ }
+ wl_list_init(&ivisurf->list_layer);
+}
+
+/**
+ * Internal API to add/remove a layer from screen.
+ */
+static void
+add_orderlayer_to_screen(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_screen *iviscrn)
+{
+ struct link_screen *link_scrn = NULL;
+
+ link_scrn = malloc(sizeof *link_scrn);
+ if (link_scrn == NULL) {
+ weston_log("fails to allocate memory\n");
+ return;
+ }
+
+ link_scrn->iviscrn = iviscrn;
+ wl_list_init(&link_scrn->link);
+ wl_list_insert(&ivilayer->list_screen, &link_scrn->link);
+ add_link_to_layer(iviscrn, link_scrn);
+}
+
+static void
+remove_orderlayer_from_screen(struct ivi_layout_layer *ivilayer)
+{
+ struct link_screen *link_scrn = NULL;
+ struct link_screen *next = NULL;
+
+ wl_list_for_each_safe(link_scrn, next, &ivilayer->list_screen, link) {
+ if (!wl_list_empty(&link_scrn->link)) {
+ wl_list_remove(&link_scrn->link);
+ }
+ free(link_scrn);
+ }
+ wl_list_init(&ivilayer->list_screen);
+}
+
+/**
+ * Internal API to add/remove a layer from screen.
+ */
+static struct ivi_layout_surface *
+get_surface(struct wl_list *list_surf, uint32_t id_surface)
+{
+ struct ivi_layout_surface *ivisurf;
+
+ wl_list_for_each(ivisurf, list_surf, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+static struct ivi_layout_layer *
+get_layer(struct wl_list *list_layer, uint32_t id_layer)
+{
+ struct ivi_layout_layer *ivilayer;
+
+ wl_list_for_each(ivilayer, list_layer, link) {
+ if (ivilayer->id_layer == id_layer) {
+ return ivilayer;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Called at destruction of ivi_surface
+ */
+static void
+westonsurface_destroy_from_ivisurface(struct wl_listener *listener, void *data)
+{
+ struct ivi_layout_surface *ivisurf = NULL;
+
+ ivisurf = container_of(listener, struct ivi_layout_surface,
+ surface_destroy_listener);
+ ivisurf->surface = NULL;
+ ivisurf->view = NULL;
+ ivi_layout_surfaceRemove(ivisurf);
+}
+
+/**
+ * Internal API to check layer/surface already added in layer/screen.
+ * Called by ivi_layout_layerAddSurface/ivi_layout_screenAddLayer
+ */
+static int
+is_surface_in_layer(struct ivi_layout_surface *ivisurf,
+ struct ivi_layout_layer *ivilayer)
+{
+ struct ivi_layout_surface *surf = NULL;
+
+ wl_list_for_each(surf, &ivilayer->pending.list_surface, pending.link) {
+ if (surf->id_surface == ivisurf->id_surface) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+is_layer_in_screen(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_screen *iviscrn)
+{
+ struct ivi_layout_layer *layer = NULL;
+
+ wl_list_for_each(layer, &iviscrn->pending.list_layer, pending.link) {
+ if (layer->id_layer == ivilayer->id_layer) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Internal API to initialize screens found from output_list of weston_compositor.
+ * Called by ivi_layout_initWithCompositor.
+ */
+static void
+create_screen(struct weston_compositor *ec)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_screen *iviscrn = NULL;
+ struct weston_output *output = NULL;
+ int32_t count = 0;
+
+ wl_list_for_each(output, &ec->output_list, link) {
+ iviscrn = calloc(1, sizeof *iviscrn);
+ if (iviscrn == NULL) {
+ weston_log("fails to allocate memory\n");
+ continue;
+ }
+
+ wl_list_init(&iviscrn->link);
+ iviscrn->layout = layout;
+
+ iviscrn->id_screen = count;
+ count++;
+
+ iviscrn->output = output;
+ iviscrn->event_mask = 0;
+
+ wl_list_init(&iviscrn->pending.list_layer);
+ wl_list_init(&iviscrn->pending.link);
+
+ wl_list_init(&iviscrn->order.list_layer);
+ wl_list_init(&iviscrn->order.link);
+
+ wl_list_init(&iviscrn->link_to_layer);
+
+ wl_list_insert(&layout->list_screen, &iviscrn->link);
+ }
+}
+
+/**
+ * Internal APIs to initialize properties of surface/layer when they are created.
+ */
+static void
+init_layerProperties(struct ivi_layout_LayerProperties *prop,
+ int32_t width, int32_t height)
+{
+ memset(prop, 0, sizeof *prop);
+ prop->opacity = wl_fixed_from_double(1.0);
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+ prop->destWidth = width;
+ prop->destHeight = height;
+}
+
+static void
+init_surfaceProperties(struct ivi_layout_SurfaceProperties *prop)
+{
+ memset(prop, 0, sizeof *prop);
+ prop->opacity = wl_fixed_from_double(1.0);
+}
+
+/**
+ * Internal APIs to be called from ivi_layout_commitChanges.
+ */
+static void
+update_opacity(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *ivisurf)
+{
+ double layer_alpha = wl_fixed_to_double(ivilayer->prop.opacity);
+ double surf_alpha = wl_fixed_to_double(ivisurf->prop.opacity);
+
+ if ((ivilayer->event_mask & IVI_NOTIFICATION_OPACITY) ||
+ (ivisurf->event_mask & IVI_NOTIFICATION_OPACITY)) {
+ if (ivisurf->view == NULL) {
+ return;
+ }
+ ivisurf->view->alpha = layer_alpha * surf_alpha;
+ }
+}
+
+static void
+update_surface_orientation(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->surface_rotation.matrix;
+ float width = 0.0f;
+ float height = 0.0f;
+ float v_sin = 0.0f;
+ float v_cos = 0.0f;
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float sx = 1.0f;
+ float sy = 1.0f;
+
+ if (view == NULL) {
+ return;
+ }
+
+ if ((ivilayer->prop.destWidth == 0) ||
+ (ivilayer->prop.destHeight == 0)) {
+ return;
+ }
+ width = (float)ivilayer->prop.destWidth;
+ height = (float)ivilayer->prop.destHeight;
+
+ switch (ivisurf->prop.orientation) {
+ case IVI_LAYOUT_SURFACE_ORIENTATION_0_DEGREES:
+ v_sin = 0.0f;
+ v_cos = 1.0f;
+ break;
+ case IVI_LAYOUT_SURFACE_ORIENTATION_90_DEGREES:
+ v_sin = 1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ case IVI_LAYOUT_SURFACE_ORIENTATION_180_DEGREES:
+ v_sin = 0.0f;
+ v_cos = -1.0f;
+ break;
+ case IVI_LAYOUT_SURFACE_ORIENTATION_270_DEGREES:
+ default:
+ v_sin = -1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ }
+ wl_list_remove(&ivisurf->surface_rotation.link);
+ weston_view_geometry_dirty(view);
+
+ weston_matrix_init(matrix);
+ cx = 0.5f * width;
+ cy = 0.5f * height;
+ weston_matrix_translate(matrix, -cx, -cy, 0.0f);
+ weston_matrix_rotate_xy(matrix, v_cos, v_sin);
+ weston_matrix_scale(matrix, sx, sy, 1.0);
+ weston_matrix_translate(matrix, cx, cy, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->surface_rotation.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_layer_orientation(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *ivisurf)
+{
+ struct weston_surface *es = ivisurf->surface;
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->layer_rotation.matrix;
+ struct weston_output *output = NULL;
+ float width = 0.0f;
+ float height = 0.0f;
+ float v_sin = 0.0f;
+ float v_cos = 0.0f;
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float sx = 1.0f;
+ float sy = 1.0f;
+
+ if (es == NULL || view == NULL) {
+ return;
+ }
+
+ output = es->output;
+ if (output == NULL) {
+ return;
+ }
+ if ((output->width == 0) || (output->height == 0)) {
+ return;
+ }
+ width = (float)output->width;
+ height = (float)output->height;
+
+ switch (ivilayer->prop.orientation) {
+ case IVI_LAYOUT_SURFACE_ORIENTATION_0_DEGREES:
+ v_sin = 0.0f;
+ v_cos = 1.0f;
+ break;
+ case IVI_LAYOUT_SURFACE_ORIENTATION_90_DEGREES:
+ v_sin = 1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ case IVI_LAYOUT_SURFACE_ORIENTATION_180_DEGREES:
+ v_sin = 0.0f;
+ v_cos = -1.0f;
+ break;
+ case IVI_LAYOUT_SURFACE_ORIENTATION_270_DEGREES:
+ default:
+ v_sin = -1.0f;
+ v_cos = 0.0f;
+ sx = width / height;
+ sy = height / width;
+ break;
+ }
+ wl_list_remove(&ivisurf->layer_rotation.link);
+ weston_view_geometry_dirty(view);
+
+ weston_matrix_init(matrix);
+ cx = 0.5f * width;
+ cy = 0.5f * height;
+ weston_matrix_translate(matrix, -cx, -cy, 0.0f);
+ weston_matrix_rotate_xy(matrix, v_cos, v_sin);
+ weston_matrix_scale(matrix, sx, sy, 1.0);
+ weston_matrix_translate(matrix, cx, cy, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->layer_rotation.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_surface_position(struct ivi_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ float tx = (float)ivisurf->prop.destX;
+ float ty = (float)ivisurf->prop.destY;
+ struct weston_matrix *matrix = &ivisurf->surface_pos.matrix;
+
+ if (view == NULL) {
+ return;
+ }
+
+ wl_list_remove(&ivisurf->surface_pos.link);
+
+ weston_matrix_init(matrix);
+ weston_matrix_translate(matrix, tx, ty, 0.0f);
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->surface_pos.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+
+#if 0
+ /* disable zoom animation */
+ weston_zoom_run(es, 0.0, 1.0, NULL, NULL);
+#endif
+
+}
+
+static void
+update_layer_position(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->layer_pos.matrix;
+ float tx = (float)ivilayer->prop.destX;
+ float ty = (float)ivilayer->prop.destY;
+
+ if (view == NULL) {
+ return;
+ }
+
+ wl_list_remove(&ivisurf->layer_pos.link);
+
+ weston_matrix_init(matrix);
+ weston_matrix_translate(matrix, tx, ty, 0.0f);
+ wl_list_insert(
+ &view->geometry.transformation_list,
+ &ivisurf->layer_pos.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_scale(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *ivisurf)
+{
+ struct weston_view *view = ivisurf->view;
+ struct weston_matrix *matrix = &ivisurf->scaling.matrix;
+ float sx = 0.0f;
+ float sy = 0.0f;
+ float lw = 0.0f;
+ float sw = 0.0f;
+ float lh = 0.0f;
+ float sh = 0.0f;
+
+ if (view == NULL) {
+ return;
+ }
+
+ if (ivisurf->prop.sourceWidth == 0 && ivisurf->prop.sourceHeight == 0) {
+ ivisurf->prop.sourceWidth = ivisurf->buffer_width;
+ ivisurf->prop.sourceHeight = ivisurf->buffer_height;
+
+ if (ivisurf->prop.destWidth == 0 && ivisurf->prop.destHeight == 0) {
+ ivisurf->prop.destWidth = ivisurf->buffer_width;
+ ivisurf->prop.destHeight = ivisurf->buffer_height;
+ }
+ }
+
+ lw = ((float)ivilayer->prop.destWidth / ivilayer->prop.sourceWidth );
+ sw = ((float)ivisurf->prop.destWidth / ivisurf->prop.sourceWidth );
+ lh = ((float)ivilayer->prop.destHeight / ivilayer->prop.sourceHeight);
+ sh = ((float)ivisurf->prop.destHeight / ivisurf->prop.sourceHeight );
+ sx = sw * lw;
+ sy = sh * lh;
+
+ wl_list_remove(&ivisurf->scaling.link);
+ weston_matrix_init(matrix);
+ weston_matrix_scale(matrix, sx, sy, 1.0f);
+
+ wl_list_insert(&view->geometry.transformation_list,
+ &ivisurf->scaling.link);
+
+ weston_view_set_transform_parent(view, NULL);
+ weston_view_update_transform(view);
+}
+
+static void
+update_prop(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *ivisurf)
+{
+ if (ivilayer->event_mask | ivisurf->event_mask) {
+ update_opacity(ivilayer, ivisurf);
+ update_layer_orientation(ivilayer, ivisurf);
+ update_layer_position(ivilayer, ivisurf);
+ update_surface_position(ivisurf);
+ update_surface_orientation(ivilayer, ivisurf);
+ update_scale(ivilayer, ivisurf);
+
+ ivisurf->update_count++;
+
+ if (ivisurf->view != NULL) {
+ weston_view_geometry_dirty(ivisurf->view);
+ }
+
+ if (ivisurf->surface != NULL) {
+ weston_surface_damage(ivisurf->surface);
+ }
+ }
+}
+
+static void
+commit_changes(struct ivi_layout *layout)
+{
+ struct ivi_layout_screen *iviscrn = NULL;
+ struct ivi_layout_layer *ivilayer = NULL;
+ struct ivi_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, order.link) {
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, order.link) {
+ update_prop(ivilayer, ivisurf);
+ }
+ }
+ }
+}
+
+static void
+commit_list_surface(struct ivi_layout *layout)
+{
+ struct ivi_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ ivisurf->prop = ivisurf->pending.prop;
+ }
+}
+
+static void
+commit_list_layer(struct ivi_layout *layout)
+{
+ struct ivi_layout_layer *ivilayer = NULL;
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_surface *next = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ ivilayer->prop = ivilayer->pending.prop;
+
+ if (!(ivilayer->event_mask &
+ (IVI_NOTIFICATION_ADD | IVI_NOTIFICATION_REMOVE)) ) {
+ continue;
+ }
+
+ wl_list_for_each_safe(ivisurf, next,
+ &ivilayer->order.list_surface, order.link) {
+ remove_ordersurface_from_layer(ivisurf);
+
+ if (!wl_list_empty(&ivisurf->order.link)) {
+ wl_list_remove(&ivisurf->order.link);
+ }
+
+ wl_list_init(&ivisurf->order.link);
+ }
+
+ wl_list_init(&ivilayer->order.list_surface);
+ wl_list_for_each(ivisurf, &ivilayer->pending.list_surface,
+ pending.link) {
+ if(!wl_list_empty(&ivisurf->order.link)){
+ wl_list_remove(&ivisurf->order.link);
+ wl_list_init(&ivisurf->order.link);
+ }
+
+ wl_list_insert(&ivilayer->order.list_surface,
+ &ivisurf->order.link);
+ add_ordersurface_to_layer(ivisurf, ivilayer);
+ }
+ }
+}
+
+static void
+commit_list_screen(struct ivi_layout *layout)
+{
+ struct ivi_layout_screen *iviscrn = NULL;
+ struct ivi_layout_layer *ivilayer = NULL;
+ struct ivi_layout_layer *next = NULL;
+ struct ivi_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ if (iviscrn->event_mask & IVI_NOTIFICATION_ADD) {
+ wl_list_for_each_safe(ivilayer, next,
+ &iviscrn->order.list_layer, order.link) {
+ remove_orderlayer_from_screen(ivilayer);
+
+ if (!wl_list_empty(&ivilayer->order.link)) {
+ wl_list_remove(&ivilayer->order.link);
+ }
+
+ wl_list_init(&ivilayer->order.link);
+ }
+
+ wl_list_init(&iviscrn->order.list_layer);
+ wl_list_for_each(ivilayer, &iviscrn->pending.list_layer,
+ pending.link) {
+ wl_list_insert(&iviscrn->order.list_layer,
+ &ivilayer->order.link);
+ add_orderlayer_to_screen(ivilayer, iviscrn);
+ }
+ iviscrn->event_mask = 0;
+ }
+
+ /* Clear view list of layout layer */
+ wl_list_init(&layout->layout_layer.view_list);
+
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, order.link) {
+
+ if (ivilayer->prop.visibility == 0)
+ continue;
+
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, order.link) {
+
+ if (ivisurf->prop.visibility == 0)
+ continue;
+ if (ivisurf->surface == NULL || ivisurf->view == NULL)
+ continue;
+
+ wl_list_insert(&layout->layout_layer.view_list,
+ &ivisurf->view->layer_link);
+
+ ivisurf->surface->output = iviscrn->output;
+ }
+ }
+
+ break;
+ }
+}
+
+static void
+send_surface_prop(struct ivi_layout_surface *ivisurf)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+
+ wl_list_for_each(notification, &ivisurf->list_notification, link) {
+ notification->callback(ivisurf, &ivisurf->prop,
+ ivisurf->event_mask,
+ notification->userdata);
+ }
+
+ ivisurf->event_mask = 0;
+}
+
+static void
+send_layer_prop(struct ivi_layout_layer *ivilayer)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+
+ wl_list_for_each(notification, &ivilayer->list_notification, link) {
+ notification->callback(ivilayer, &ivilayer->prop,
+ ivilayer->event_mask,
+ notification->userdata);
+ }
+
+ ivilayer->event_mask = 0;
+}
+
+static void
+send_prop(struct ivi_layout *layout)
+{
+ struct ivi_layout_layer *ivilayer = NULL;
+ struct ivi_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ send_layer_prop(ivilayer);
+ }
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ send_surface_prop(ivisurf);
+ }
+}
+
+/**
+ * Exported APIs of ivi-layout library are implemented from here.
+ * Brief of APIs is described in ivi-layout-export.h.
+ */
+WL_EXPORT int32_t
+ivi_layout_addNotificationCreateLayer(layerCreateNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_layerCreateNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("ivi_layout_addNotificationCreateLayer: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->layer_notification.list_create, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT void
+ivi_layout_removeNotificationCreateLayer(layerCreateNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_layerCreateNotification *link = NULL;
+ struct link_layerCreateNotification *next = NULL;
+
+ wl_list_for_each_safe(link, next, &layout->layer_notification.list_create, link) {
+ if ((link->callback == callback) &&
+ (link->userdata == userdata)) {
+ if (!wl_list_empty(&link->link)) {
+ wl_list_remove(&link->link);
+ }
+
+ free(link);
+ }
+ }
+}
+
+WL_EXPORT int32_t
+ivi_layout_addNotificationRemoveLayer(layerRemoveNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_layerRemoveNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("ivi_layout_addNotificationRemoveLayer: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->layer_notification.list_remove, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT void
+ivi_layout_removeNotificationRemoveLayer(layerRemoveNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_layerRemoveNotification *link = NULL;
+ struct link_layerRemoveNotification *next = NULL;
+
+ wl_list_for_each_safe(link, next, &layout->layer_notification.list_remove, link) {
+ if ((link->callback == callback) &&
+ (link->userdata == userdata)) {
+ if (!wl_list_empty(&link->link)) {
+ wl_list_remove(&link->link);
+ }
+
+ free(link);
+ }
+ }
+}
+
+WL_EXPORT int32_t
+ivi_layout_addNotificationCreateSurface(surfaceCreateNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("ivi_layout_addNotificationCreateSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_create, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT void
+ivi_layout_removeNotificationCreateSurface(surfaceCreateNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_surfaceCreateNotification *link = NULL;
+ struct link_surfaceCreateNotification *next = NULL;
+
+ wl_list_for_each_safe(link, next, &layout->surface_notification.list_create, link) {
+ if ((link->callback == callback) &&
+ (link->userdata == userdata)) {
+ if (!wl_list_empty(&link->link)) {
+ wl_list_remove(&link->link);
+ }
+
+ free(link);
+ }
+ }
+}
+
+WL_EXPORT int32_t
+ivi_layout_addNotificationRemoveSurface(surfaceRemoveNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_surfaceRemoveNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("ivi_layout_addNotificationRemoveSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_remove, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT void
+ivi_layout_removeNotificationRemoveSurface(surfaceRemoveNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_surfaceRemoveNotification *link = NULL;
+ struct link_surfaceRemoveNotification *next = NULL;
+
+ wl_list_for_each_safe(link, next, &layout->surface_notification.list_remove, link) {
+ if ((link->callback == callback) &&
+ (link->userdata == userdata)) {
+ if (!wl_list_empty(&link->link)) {
+ wl_list_remove(&link->link);
+ }
+
+ free(link);
+ }
+ }
+}
+
+WL_EXPORT int32_t
+ivi_layout_addNotificationConfigureSurface(surfaceConfigureNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_surfaceConfigureNotification *notification = NULL;
+
+ if (callback == NULL) {
+ weston_log("ivi_layout_addNotificationConfigureSurface: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&layout->surface_notification.list_configure, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT void
+ivi_layout_removeNotificationConfigureSurface(surfaceConfigureNotificationFunc callback,
+ void *userdata)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_surfaceConfigureNotification *link = NULL;
+ struct link_surfaceConfigureNotification *next = NULL;
+
+ wl_list_for_each_safe(link, next, &layout->surface_notification.list_configure, link) {
+ if ((link->callback == callback) &&
+ (link->userdata == userdata)) {
+ if (!wl_list_empty(&link->link)) {
+ wl_list_remove(&link->link);
+ }
+
+ free(link);
+ }
+ }
+}
+
+WL_EXPORT uint32_t
+ivi_layout_getIdOfSurface(struct ivi_layout_surface *ivisurf)
+{
+ return ivisurf->id_surface;
+}
+
+WL_EXPORT uint32_t
+ivi_layout_getIdOfLayer(struct ivi_layout_layer *ivilayer)
+{
+ return ivilayer->id_layer;
+}
+
+WL_EXPORT struct ivi_layout_layer *
+ivi_layout_getLayerFromId(uint32_t id_layer)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_layer *ivilayer = NULL;
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ if (ivilayer->id_layer == id_layer) {
+ return ivilayer;
+ }
+ }
+
+ return NULL;
+}
+
+WL_EXPORT struct ivi_layout_surface *
+ivi_layout_getSurfaceFromId(uint32_t id_surface)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_surface *ivisurf = NULL;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ if (ivisurf->id_surface == id_surface) {
+ return ivisurf;
+ }
+ }
+
+ return NULL;
+}
+
+WL_EXPORT struct ivi_layout_screen *
+ivi_layout_getScreenFromId(uint32_t id_screen)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_screen *iviscrn = NULL;
+ (void)id_screen;
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+//FIXME : select iviscrn from list_screen by id_screen
+ return iviscrn;
+ break;
+ }
+
+ return NULL;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getScreenResolution(struct ivi_layout_screen *iviscrn,
+ uint32_t *pWidth, uint32_t *pHeight)
+{
+ struct weston_output *output = NULL;
+
+ if (pWidth == NULL || pHeight == NULL) {
+ weston_log("ivi_layout_getScreenResolution: invalid argument\n");
+ return -1;
+ }
+
+ output = iviscrn->output;
+ *pWidth = output->current_mode->width;
+ *pHeight = output->current_mode->height;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceAddNotification(struct ivi_layout_surface *ivisurf,
+ surfacePropertyNotificationFunc callback,
+ void *userdata)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+
+ if (ivisurf == NULL || callback == NULL) {
+ weston_log("ivi_layout_surfaceAddNotification: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&ivisurf->list_notification, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceRemoveNotification(struct ivi_layout_surface *ivisurf)
+{
+ struct link_surfacePropertyNotification *notification = NULL;
+ struct link_surfacePropertyNotification *next = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("ivi_layout_surfaceRemoveNotification: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(notification, next,
+ &ivisurf->list_notification, link) {
+ if (!wl_list_empty(&notification->link)) {
+ wl_list_remove(&notification->link);
+ }
+ free(notification);
+ }
+ wl_list_init(&ivisurf->list_notification);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceRemove(struct ivi_layout_surface *ivisurf)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_surfaceRemoveNotification *notification = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("ivi_layout_surfaceRemove: invalid argument\n");
+ return -1;
+ }
+
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ if (!wl_list_empty(&ivisurf->order.link)) {
+ wl_list_remove(&ivisurf->order.link);
+ }
+ if (!wl_list_empty(&ivisurf->link)) {
+ wl_list_remove(&ivisurf->link);
+ }
+ remove_ordersurface_from_layer(ivisurf);
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_remove, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ free(ivisurf);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_UpdateInputEventAcceptanceOn(struct ivi_layout_surface *ivisurf,
+ uint32_t devices, uint32_t acceptance)
+{
+ /* TODO */
+ (void)ivisurf;
+ (void)devices;
+ (void)acceptance;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceInitialize(struct ivi_layout_surface **pSurfaceId)
+{
+ /* TODO */
+ (void)pSurfaceId;
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getPropertiesOfLayer(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_LayerProperties *pLayerProperties)
+{
+ if (ivilayer == NULL || pLayerProperties == NULL) {
+ weston_log("ivi_layout_getPropertiesOfLayer: invalid argument\n");
+ return -1;
+ }
+
+ *pLayerProperties = ivilayer->prop;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getNumberOfHardwareLayers(uint32_t id_screen,
+ uint32_t *pNumberOfHardwareLayers)
+{
+ /* TODO */
+ (void)id_screen;
+ (void)pNumberOfHardwareLayers;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getScreens(uint32_t *pLength, ivi_layout_screen_ptr **ppArray)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_screen *iviscrn = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("ivi_layout_getScreens: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_screen);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(ivi_layout_screen_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(iviscrn, &layout->list_screen, link) {
+ (*ppArray)[n++] = iviscrn;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getScreensUnderLayer(struct ivi_layout_layer *ivilayer,
+ uint32_t *pLength,
+ ivi_layout_screen_ptr **ppArray)
+{
+ struct link_screen *link_scrn = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("ivi_layout_getScreensUnderLayer: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivilayer->list_screen);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(ivi_layout_screen_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(link_scrn, &ivilayer->list_screen, link) {
+ (*ppArray)[n++] = link_scrn->iviscrn;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getLayers(uint32_t *pLength, ivi_layout_layer_ptr **ppArray)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_layer *ivilayer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("ivi_layout_getLayers: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(ivi_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ (*ppArray)[n++] = ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getLayersOnScreen(struct ivi_layout_screen *iviscrn,
+ uint32_t *pLength,
+ ivi_layout_layer_ptr **ppArray)
+{
+ struct ivi_layout_layer *ivilayer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (iviscrn == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("ivi_layout_getLayersOnScreen: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&iviscrn->order.list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(ivi_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivilayer, &iviscrn->order.list_layer, link) {
+ (*ppArray)[n++] = ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getLayersUnderSurface(struct ivi_layout_surface *ivisurf,
+ uint32_t *pLength,
+ ivi_layout_layer_ptr **ppArray)
+{
+ struct link_layer *link_layer = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivisurf == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("ivi_layout_getLayers: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivisurf->list_layer);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(ivi_layout_layer_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(link_layer, &ivisurf->list_layer, link) {
+ (*ppArray)[n++] = link_layer->ivilayer;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getSurfaces(uint32_t *pLength, ivi_layout_surface_ptr **ppArray)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_surface *ivisurf = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (pLength == NULL || ppArray == NULL) {
+ weston_log("ivi_layout_getSurfaces: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&layout->list_surface);
+
+ if (length != 0){
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(ivi_layout_surface_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ (*ppArray)[n++] = ivisurf;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getSurfacesOnLayer(struct ivi_layout_layer *ivilayer,
+ uint32_t *pLength,
+ ivi_layout_surface_ptr **ppArray)
+{
+ struct ivi_layout_surface *ivisurf = NULL;
+ uint32_t length = 0;
+ uint32_t n = 0;
+
+ if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
+ weston_log("ivi_layout_getSurfaceIDsOnLayer: invalid argument\n");
+ return -1;
+ }
+
+ length = wl_list_length(&ivilayer->order.list_surface);
+
+ if (length != 0) {
+ /* the Array must be free by module which called this function */
+ *ppArray = calloc(length, sizeof(ivi_layout_surface_ptr));
+ if (*ppArray == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ wl_list_for_each(ivisurf, &ivilayer->order.list_surface, order.link) {
+ (*ppArray)[n++] = ivisurf;
+ }
+ }
+
+ *pLength = length;
+
+ return 0;
+}
+
+WL_EXPORT struct ivi_layout_layer *
+ivi_layout_layerCreateWithDimension(uint32_t id_layer,
+ uint32_t width, uint32_t height)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_layer *ivilayer = NULL;
+ struct link_layerCreateNotification *notification = NULL;
+
+ ivilayer = get_layer(&layout->list_layer, id_layer);
+ if (ivilayer != NULL) {
+ weston_log("id_layer is already created\n");
+ return ivilayer;
+ }
+
+ ivilayer = calloc(1, sizeof *ivilayer);
+ if (ivilayer == NULL) {
+ weston_log("fails to allocate memory\n");
+ return NULL;
+ }
+
+ wl_list_init(&ivilayer->link);
+ wl_list_init(&ivilayer->list_notification);
+ wl_list_init(&ivilayer->list_screen);
+ wl_list_init(&ivilayer->link_to_surface);
+ ivilayer->layout = layout;
+ ivilayer->id_layer = id_layer;
+
+ init_layerProperties(&ivilayer->prop, width, height);
+ ivilayer->event_mask = 0;
+
+ wl_list_init(&ivilayer->pending.list_surface);
+ wl_list_init(&ivilayer->pending.link);
+ ivilayer->pending.prop = ivilayer->prop;
+
+ wl_list_init(&ivilayer->order.list_surface);
+ wl_list_init(&ivilayer->order.link);
+
+ wl_list_insert(&layout->list_layer, &ivilayer->link);
+
+ wl_list_for_each(notification,
+ &layout->layer_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivilayer, notification->userdata);
+ }
+ }
+
+ return ivilayer;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerRemove(struct ivi_layout_layer *ivilayer)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_layerRemoveNotification *notification = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("ivi_layout_layerRemove: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each(notification,
+ &layout->layer_notification.list_remove, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivilayer, notification->userdata);
+ }
+ }
+
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ if (!wl_list_empty(&ivilayer->order.link)) {
+ wl_list_remove(&ivilayer->order.link);
+ }
+ if (!wl_list_empty(&ivilayer->link)) {
+ wl_list_remove(&ivilayer->link);
+ }
+ remove_orderlayer_from_screen(ivilayer);
+ remove_link_to_surface(ivilayer);
+
+ free(ivilayer);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerGetType(struct ivi_layout_layer *ivilayer,
+ uint32_t *pLayerType)
+{
+ /* TODO */
+ (void)ivilayer;
+ (void)pLayerType;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetVisibility(struct ivi_layout_layer *ivilayer,
+ uint32_t newVisibility)
+{
+ struct ivi_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("ivi_layout_layerSetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->visibility = newVisibility;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_VISIBILITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerGetVisibility(struct ivi_layout_layer *ivilayer, uint32_t *pVisibility)
+{
+ if (ivilayer == NULL || pVisibility == NULL) {
+ weston_log("ivi_layout_layerGetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ *pVisibility = ivilayer->prop.visibility;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetOpacity(struct ivi_layout_layer *ivilayer,
+ float opacity)
+{
+ struct ivi_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("ivi_layout_layerSetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->opacity = opacity;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_OPACITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerGetOpacity(struct ivi_layout_layer *ivilayer,
+ float *pOpacity)
+{
+ if (ivilayer == NULL || pOpacity == NULL) {
+ weston_log("ivi_layout_layerGetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ *pOpacity = ivilayer->prop.opacity;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetSourceRectangle(struct ivi_layout_layer *ivilayer,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct ivi_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("ivi_layout_layerSetSourceRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->sourceX = x;
+ prop->sourceY = y;
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetDestinationRectangle(struct ivi_layout_layer *ivilayer,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct ivi_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("ivi_layout_layerSetDestinationRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->destX = x;
+ prop->destY = y;
+ prop->destWidth = width;
+ prop->destHeight = height;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_DEST_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerGetDimension(struct ivi_layout_layer *ivilayer,
+ uint32_t *pDimension)
+{
+ if (ivilayer == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("ivi_layout_layerGetDimension: invalid argument\n");
+ return -1;
+ }
+
+ pDimension[0] = ivilayer->prop.destX;
+ pDimension[1] = ivilayer->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetDimension(struct ivi_layout_layer *ivilayer,
+ uint32_t *pDimension)
+{
+ struct ivi_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("ivi_layout_layerSetDimension: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+
+ prop->destWidth = pDimension[0];
+ prop->destHeight = pDimension[1];
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_DIMENSION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerGetPosition(struct ivi_layout_layer *ivilayer, int32_t *pPosition)
+{
+ if (ivilayer == NULL || pPosition == NULL) {
+ weston_log("ivi_layout_layerGetPosition: invalid argument\n");
+ return -1;
+ }
+
+ pPosition[0] = ivilayer->prop.destX;
+ pPosition[1] = ivilayer->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetPosition(struct ivi_layout_layer *ivilayer, int32_t *pPosition)
+{
+ struct ivi_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL || pPosition == NULL) {
+ weston_log("ivi_layout_layerSetPosition: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->destX = pPosition[0];
+ prop->destY = pPosition[1];
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_POSITION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetOrientation(struct ivi_layout_layer *ivilayer,
+ uint32_t orientation)
+{
+ struct ivi_layout_LayerProperties *prop = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("ivi_layout_layerSetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivilayer->pending.prop;
+ prop->orientation = orientation;
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ORIENTATION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerGetOrientation(struct ivi_layout_layer *ivilayer,
+ uint32_t *pOrientation)
+{
+ if (ivilayer == NULL || pOrientation == NULL) {
+ weston_log("ivi_layout_layerGetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ *pOrientation = ivilayer->prop.orientation;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetChromaKey(struct ivi_layout_layer *ivilayer, uint32_t* pColor)
+{
+ /* TODO */
+ (void)ivilayer;
+ (void)pColor;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerSetRenderOrder(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface **pSurface,
+ uint32_t number)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_surface *next = NULL;
+ uint32_t *id_surface = NULL;
+ uint32_t i = 0;
+
+ if (ivilayer == NULL) {
+ weston_log("ivi_layout_layerSetRenderOrder: invalid argument\n");
+ return -1;
+ }
+
+ if (pSurface == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < number; i++) {
+ id_surface = &pSurface[i]->id_surface;
+
+ wl_list_for_each(ivisurf, &layout->list_surface, link) {
+ if (*id_surface != ivisurf->id_surface) {
+ continue;
+ }
+
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ wl_list_insert(&ivilayer->pending.list_surface,
+ &ivisurf->pending.link);
+ break;
+ }
+ }
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerGetCapabilities(struct ivi_layout_layer *ivilayer,
+ uint32_t *pCapabilities)
+{
+ /* TODO */
+ (void)ivilayer;
+ (void)pCapabilities;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerTypeGetCapabilities(uint32_t layerType,
+ uint32_t *pCapabilities)
+{
+ /* TODO */
+ (void)layerType;
+ (void)pCapabilities;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceSetVisibility(struct ivi_layout_surface *ivisurf,
+ uint32_t newVisibility)
+{
+ struct ivi_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("ivi_layout_surfaceSetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->visibility = newVisibility;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_VISIBILITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceGetVisibility(struct ivi_layout_surface *ivisurf,
+ uint32_t *pVisibility)
+{
+ if (ivisurf == NULL || pVisibility == NULL) {
+ weston_log("ivi_layout_surfaceGetVisibility: invalid argument\n");
+ return -1;
+ }
+
+ *pVisibility = ivisurf->prop.visibility;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceSetOpacity(struct ivi_layout_surface *ivisurf,
+ float opacity)
+{
+ struct ivi_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("ivi_layout_surfaceSetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->opacity = opacity;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_OPACITY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceGetOpacity(struct ivi_layout_surface *ivisurf,
+ float *pOpacity)
+{
+ if (ivisurf == NULL || pOpacity == NULL) {
+ weston_log("ivi_layout_surfaceGetOpacity: invalid argument\n");
+ return -1;
+ }
+
+ *pOpacity = ivisurf->prop.opacity;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_SetKeyboardFocusOn(struct ivi_layout_surface *ivisurf)
+{
+ /* TODO */
+ (void)ivisurf;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_GetKeyboardFocusSurfaceId(struct ivi_layout_surface **pSurfaceId)
+{
+ /* TODO */
+ (void)pSurfaceId;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceSetDestinationRectangle(struct ivi_layout_surface *ivisurf,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct ivi_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("ivi_layout_surfaceSetDestinationRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destX = x;
+ prop->destY = y;
+ prop->destWidth = width;
+ prop->destHeight = height;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_DEST_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceSetDimension(struct ivi_layout_surface *ivisurf, uint32_t *pDimension)
+{
+ struct ivi_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("ivi_layout_surfaceSetDimension: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destWidth = pDimension[0];
+ prop->destHeight = pDimension[1];
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_DIMENSION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceGetDimension(struct ivi_layout_surface *ivisurf,
+ uint32_t *pDimension)
+{
+ if (ivisurf == NULL || &pDimension[0] == NULL || &pDimension[1] == NULL) {
+ weston_log("ivi_layout_surfaceGetDimension: invalid argument\n");
+ return -1;
+ }
+
+ pDimension[0] = ivisurf->prop.destWidth;
+ pDimension[1] = ivisurf->prop.destHeight;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceSetPosition(struct ivi_layout_surface *ivisurf,
+ int32_t *pPosition)
+{
+ struct ivi_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL || pPosition == NULL) {
+ weston_log("ivi_layout_surfaceSetPosition: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->destX = pPosition[0];
+ prop->destY = pPosition[1];
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_POSITION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceGetPosition(struct ivi_layout_surface *ivisurf,
+ int32_t *pPosition)
+{
+ if (ivisurf == NULL || pPosition == NULL) {
+ weston_log("ivi_layout_surfaceGetPosition: invalid argument\n");
+ return -1;
+ }
+
+ pPosition[0] = ivisurf->prop.destX;
+ pPosition[1] = ivisurf->prop.destY;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceSetOrientation(struct ivi_layout_surface *ivisurf,
+ uint32_t orientation)
+{
+ struct ivi_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("ivi_layout_surfaceSetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->orientation = orientation;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_ORIENTATION;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceGetOrientation(struct ivi_layout_surface *ivisurf,
+ uint32_t *pOrientation)
+{
+ if (ivisurf == NULL || pOrientation == NULL) {
+ weston_log("ivi_layout_surfaceGetOrientation: invalid argument\n");
+ return -1;
+ }
+
+ *pOrientation = ivisurf->prop.orientation;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceGetPixelformat(struct ivi_layout_layer *ivisurf, uint32_t *pPixelformat)
+{
+ /* TODO */
+ (void)ivisurf;
+ (void)pPixelformat;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceSetChromaKey(struct ivi_layout_surface *ivisurf, uint32_t* pColor)
+{
+ /* TODO */
+ (void)ivisurf;
+ (void)pColor;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_screenAddLayer(struct ivi_layout_screen *iviscrn,
+ struct ivi_layout_layer *addlayer)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_layer *ivilayer = NULL;
+ struct ivi_layout_layer *next = NULL;
+ int is_layer_in_scrn = 0;
+
+ if (iviscrn == NULL || addlayer == NULL) {
+ weston_log("ivi_layout_screenAddLayer: invalid argument\n");
+ return -1;
+ }
+
+ is_layer_in_scrn = is_layer_in_screen(addlayer, iviscrn);
+ if (is_layer_in_scrn == 1) {
+ weston_log("ivi_layout_screenAddLayer: addlayer is already available\n");
+ return 0;
+ }
+
+ wl_list_for_each_safe(ivilayer, next, &layout->list_layer, link) {
+ if (ivilayer->id_layer == addlayer->id_layer) {
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ wl_list_init(&ivilayer->pending.link);
+ wl_list_insert(&iviscrn->pending.list_layer,
+ &ivilayer->pending.link);
+ break;
+ }
+ }
+
+ iviscrn->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_screenSetRenderOrder(struct ivi_layout_screen *iviscrn,
+ struct ivi_layout_layer **pLayer,
+ const uint32_t number)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_layer *ivilayer = NULL;
+ struct ivi_layout_layer *next = NULL;
+ uint32_t *id_layer = NULL;
+ uint32_t i = 0;
+
+ if (iviscrn == NULL) {
+ weston_log("ivi_layout_screenSetRenderOrder: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(ivilayer, next,
+ &iviscrn->pending.list_layer, pending.link) {
+ wl_list_init(&ivilayer->pending.link);
+ }
+
+ wl_list_init(&iviscrn->pending.list_layer);
+
+ if (pLayer == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < number; i++) {
+ id_layer = &pLayer[i]->id_layer;
+ wl_list_for_each(ivilayer, &layout->list_layer, link) {
+ if (*id_layer != ivilayer->id_layer) {
+ continue;
+ }
+
+ if (!wl_list_empty(&ivilayer->pending.link)) {
+ wl_list_remove(&ivilayer->pending.link);
+ }
+ wl_list_init(&ivilayer->pending.link);
+ wl_list_insert(&iviscrn->pending.list_layer,
+ &ivilayer->pending.link);
+ break;
+ }
+ }
+
+ iviscrn->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_takeScreenshot(struct ivi_layout_screen *iviscrn,
+ const char *filename)
+{
+ struct weston_output *output = NULL;
+ cairo_surface_t *cairo_surf = NULL;
+ int32_t i = 0;
+ int32_t width = 0;
+ int32_t height = 0;
+ int32_t stride = 0;
+ uint8_t *readpixs = NULL;
+ uint8_t *writepixs = NULL;
+ uint8_t *d = NULL;
+ uint8_t *s = NULL;
+
+ if (iviscrn == NULL || filename == NULL) {
+ weston_log("ivi_layout_takeScreenshot: invalid argument\n");
+ return -1;
+ }
+
+ output = iviscrn->output;
+ output->disable_planes--;
+
+ width = output->current_mode->width;
+ height = output->current_mode->height;
+ stride = width * (PIXMAN_FORMAT_BPP(output->compositor->read_format) / 8);
+
+ readpixs = malloc(stride * height);
+ if (readpixs == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+ writepixs = malloc(stride * height);
+ if (writepixs == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ output->compositor->renderer->read_pixels(output,
+ output->compositor->read_format, readpixs,
+ 0, 0, width, height);
+
+ s = readpixs;
+ d = writepixs + stride * (height - 1);
+
+ for (i = 0; i < height; i++) {
+ memcpy(d, s, stride);
+ d -= stride;
+ s += stride;
+ }
+
+ cairo_surf = cairo_image_surface_create_for_data(writepixs,
+ CAIRO_FORMAT_ARGB32,
+ width, height, stride);
+ cairo_surface_write_to_png(cairo_surf, filename);
+ cairo_surface_destroy(cairo_surf);
+ free(writepixs);
+ free(readpixs);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_takeLayerScreenshot(const char *filename, struct ivi_layout_layer *ivilayer)
+{
+ /* TODO */
+ (void)filename;
+ (void)ivilayer;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_takeSurfaceScreenshot(const char *filename,
+ struct ivi_layout_surface *ivisurf)
+{
+ weston_log("ivi_layout_takeSurfaceScreenshot: "
+ "This function is not supported now\n");
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_SetOptimizationMode(uint32_t id, uint32_t mode)
+{
+ /* TODO */
+ (void)id;
+ (void)mode;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_GetOptimizationMode(uint32_t id, uint32_t *pMode)
+{
+ /* TODO */
+ (void)id;
+ (void)pMode;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerAddNotification(struct ivi_layout_layer *ivilayer,
+ layerPropertyNotificationFunc callback,
+ void *userdata)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+
+ if (ivilayer == NULL || callback == NULL) {
+ weston_log("ivi_layout_layerAddNotification: invalid argument\n");
+ return -1;
+ }
+
+ notification = malloc(sizeof *notification);
+ if (notification == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ notification->callback = callback;
+ notification->userdata = userdata;
+ wl_list_init(&notification->link);
+ wl_list_insert(&ivilayer->list_notification, &notification->link);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerRemoveNotification(struct ivi_layout_layer *ivilayer)
+{
+ struct link_layerPropertyNotification *notification = NULL;
+ struct link_layerPropertyNotification *next = NULL;
+
+ if (ivilayer == NULL) {
+ weston_log("ivi_layout_layerRemoveNotification: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(notification, next,
+ &ivilayer->list_notification, link) {
+ if (!wl_list_empty(&notification->link)) {
+ wl_list_remove(&notification->link);
+ }
+ free(notification);
+ }
+ wl_list_init(&ivilayer->list_notification);
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_getPropertiesOfSurface(struct ivi_layout_surface *ivisurf,
+ struct ivi_layout_SurfaceProperties *pSurfaceProperties)
+{
+ if (ivisurf == NULL || pSurfaceProperties == NULL) {
+ weston_log("ivi_layout_getPropertiesOfSurface: invalid argument\n");
+ return -1;
+ }
+
+ *pSurfaceProperties = ivisurf->prop;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerAddSurface(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *addsurf)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_surface *next = NULL;
+ int is_surf_in_layer = 0;
+
+ if (ivilayer == NULL || addsurf == NULL) {
+ weston_log("ivi_layout_layerAddSurface: invalid argument\n");
+ return -1;
+ }
+
+ is_surf_in_layer = is_surface_in_layer(addsurf, ivilayer);
+ if (is_surf_in_layer == 1) {
+ weston_log("ivi_layout_layerAddSurface: addsurf is already available\n");
+ return 0;
+ }
+
+ wl_list_for_each_safe(ivisurf, next, &layout->list_surface, link) {
+ if (ivisurf->id_surface == addsurf->id_surface) {
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ wl_list_insert(&ivilayer->pending.list_surface,
+ &ivisurf->pending.link);
+ break;
+ }
+ }
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_ADD;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_layerRemoveSurface(struct ivi_layout_layer *ivilayer,
+ struct ivi_layout_surface *remsurf)
+{
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_surface *next = NULL;
+
+ if (ivilayer == NULL || remsurf == NULL) {
+ weston_log("ivi_layout_layerRemoveSurface: invalid argument\n");
+ return -1;
+ }
+
+ wl_list_for_each_safe(ivisurf, next,
+ &ivilayer->pending.list_surface, pending.link) {
+ if (ivisurf->id_surface == remsurf->id_surface) {
+ if (!wl_list_empty(&ivisurf->pending.link)) {
+ wl_list_remove(&ivisurf->pending.link);
+ }
+ wl_list_init(&ivisurf->pending.link);
+ break;
+ }
+ }
+
+ ivilayer->event_mask |= IVI_NOTIFICATION_REMOVE;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_surfaceSetSourceRectangle(struct ivi_layout_surface *ivisurf,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct ivi_layout_SurfaceProperties *prop = NULL;
+
+ if (ivisurf == NULL) {
+ weston_log("ivi_layout_surfaceSetSourceRectangle: invalid argument\n");
+ return -1;
+ }
+
+ prop = &ivisurf->pending.prop;
+ prop->sourceX = x;
+ prop->sourceY = y;
+ prop->sourceWidth = width;
+ prop->sourceHeight = height;
+
+ ivisurf->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
+
+ return 0;
+}
+
+WL_EXPORT int32_t
+ivi_layout_commitChanges(void)
+{
+ struct ivi_layout *layout = get_instance();
+
+ commit_list_surface(layout);
+ commit_list_layer(layout);
+ commit_list_screen(layout);
+
+ commit_changes(layout);
+ send_prop(layout);
+ weston_compositor_schedule_repaint(layout->compositor);
+
+ return 0;
+}
+
+/***called from ivi-shell**/
+static struct weston_view *
+ivi_layout_get_weston_view(struct ivi_layout_surface *surface)
+{
+ return (surface != NULL) ? surface->view : NULL;
+}
+
+static void
+ivi_layout_surfaceConfigure(struct ivi_layout_surface *ivisurf,
+ uint32_t width, uint32_t height)
+{
+ struct ivi_layout *layout = get_instance();
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ ivisurf->buffer_width = width;
+ ivisurf->buffer_height = height;
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_configure, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+}
+
+static int32_t
+ivi_layout_surfaceSetNativeContent(struct weston_surface *surface,
+ uint32_t width,
+ uint32_t height,
+ uint32_t id_surface)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_surface *ivisurf;
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ ivisurf = get_surface(&layout->list_surface, id_surface);
+ if (ivisurf == NULL) {
+ weston_log("layout surface is not found\n");
+ return -1;
+ }
+
+ if (ivisurf->surface != NULL) {
+ if (surface != NULL) {
+ weston_log("id_surface(%d) is already set the native content\n",
+ id_surface);
+ return -1;
+ }
+
+ wl_list_remove(&ivisurf->surface_destroy_listener.link);
+ weston_view_destroy(ivisurf->view);
+
+ ivisurf->surface = NULL;
+ ivisurf->view = NULL;
+ }
+
+ if (surface == NULL)
+ return 0;
+
+ ivisurf->surface = surface;
+ ivisurf->surface_destroy_listener.notify =
+ westonsurface_destroy_from_ivisurface;
+ wl_resource_add_destroy_listener(surface->resource,
+ &ivisurf->surface_destroy_listener);
+ ivisurf->view = weston_view_create(surface);
+ if (ivisurf->view == NULL) {
+ weston_log("fails to allocate memory\n");
+ return -1;
+ }
+
+ ivisurf->buffer_width = width;
+ ivisurf->buffer_height = height;
+ ivisurf->pixelformat = IVI_LAYOUT_SURFACE_PIXELFORMAT_RGBA_8888;
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ return 0;
+}
+
+static struct ivi_layout_surface*
+ivi_layout_surfaceCreate(struct weston_surface *wl_surface,
+ uint32_t id_surface)
+{
+ struct ivi_layout *layout = get_instance();
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct link_surfaceCreateNotification *notification = NULL;
+
+ if (wl_surface == NULL) {
+ weston_log("ivi_layout_surfaceCreate: invalid argument\n");
+ return NULL;
+ }
+
+ ivisurf = get_surface(&layout->list_surface, id_surface);
+ if (ivisurf != NULL) {
+ if (ivisurf->surface != NULL) {
+ weston_log("id_surface(%d) is already created\n", id_surface);
+ return NULL;
+ } else {
+ /* if ivisurf->surface exist, wl_surface is tied to id_surface again */
+ /* This means client destroys ivi_surface once, and then tries to tie
+ the id_surface to new wl_surface again. The property of id_surface can
+ be inherited.
+ */
+ ivi_layout_surfaceSetNativeContent(
+ wl_surface, wl_surface->width, wl_surface->height, id_surface);
+ return ivisurf;
+ }
+ }
+
+ ivisurf = calloc(1, sizeof *ivisurf);
+ if (ivisurf == NULL) {
+ weston_log("fails to allocate memory\n");
+ return NULL;
+ }
+
+ wl_list_init(&ivisurf->link);
+ wl_list_init(&ivisurf->list_notification);
+ wl_list_init(&ivisurf->list_layer);
+ ivisurf->id_surface = id_surface;
+ ivisurf->layout = layout;
+
+ ivisurf->surface = wl_surface;
+ ivisurf->surface_destroy_listener.notify =
+ westonsurface_destroy_from_ivisurface;
+ wl_resource_add_destroy_listener(wl_surface->resource,
+ &ivisurf->surface_destroy_listener);
+
+ ivisurf->view = weston_view_create(wl_surface);
+ if (ivisurf->view == NULL) {
+ weston_log("fails to allocate memory\n");
+ }
+
+ ivisurf->buffer_width = 0;
+ ivisurf->buffer_height = 0;
+
+ weston_matrix_init(&ivisurf->view->transform.matrix);
+
+ weston_matrix_init(&ivisurf->surface_rotation.matrix);
+ weston_matrix_init(&ivisurf->layer_rotation.matrix);
+ weston_matrix_init(&ivisurf->surface_pos.matrix);
+ weston_matrix_init(&ivisurf->layer_pos.matrix);
+ weston_matrix_init(&ivisurf->scaling.matrix);
+
+ wl_list_init(&ivisurf->surface_rotation.link);
+ wl_list_init(&ivisurf->layer_rotation.link);
+ wl_list_init(&ivisurf->surface_pos.link);
+ wl_list_init(&ivisurf->layer_pos.link);
+ wl_list_init(&ivisurf->scaling.link);
+
+ init_surfaceProperties(&ivisurf->prop);
+ ivisurf->pixelformat = IVI_LAYOUT_SURFACE_PIXELFORMAT_RGBA_8888;
+ ivisurf->event_mask = 0;
+
+ ivisurf->pending.prop = ivisurf->prop;
+ wl_list_init(&ivisurf->pending.link);
+
+ wl_list_init(&ivisurf->order.link);
+ wl_list_init(&ivisurf->order.list_layer);
+
+ wl_list_insert(&layout->list_surface, &ivisurf->link);
+
+ wl_list_for_each(notification,
+ &layout->surface_notification.list_create, link) {
+ if (notification->callback != NULL) {
+ notification->callback(ivisurf, notification->userdata);
+ }
+ }
+
+ return ivisurf;
+}
+
+static void
+ivi_layout_initWithCompositor(struct weston_compositor *ec)
+{
+ struct ivi_layout *layout = get_instance();
+
+ layout->compositor = ec;
+
+ wl_list_init(&layout->list_surface);
+ wl_list_init(&layout->list_layer);
+ wl_list_init(&layout->list_screen);
+
+ wl_list_init(&layout->layer_notification.list_create);
+ wl_list_init(&layout->layer_notification.list_remove);
+
+ wl_list_init(&layout->surface_notification.list_create);
+ wl_list_init(&layout->surface_notification.list_remove);
+ wl_list_init(&layout->surface_notification.list_configure);
+
+ /* Add layout_layer at the last of weston_compositor.layer_list */
+ weston_layer_init(&layout->layout_layer, ec->layer_list.prev);
+
+ create_screen(ec);
+
+ struct weston_config *config = weston_config_parse("weston.ini");
+ struct weston_config_section *s =
+ weston_config_get_section(config, "ivi-shell", NULL, NULL);
+
+ /*A cursor is configured if weston.ini has keys.*/
+ char* cursor_theme = NULL;
+ weston_config_section_get_string(s, "cursor-theme", &cursor_theme, NULL);
+ if (cursor_theme)
+ free(cursor_theme);
+ else
+ wl_list_remove(&ec->cursor_layer.link);
+ weston_config_destroy(config);
+}
+
+
+WL_EXPORT struct ivi_layout_interface ivi_layout_interface = {
+ .get_weston_view = ivi_layout_get_weston_view,
+ .surfaceConfigure = ivi_layout_surfaceConfigure,
+ .surfaceSetNativeContent = ivi_layout_surfaceSetNativeContent,
+ .surfaceCreate = ivi_layout_surfaceCreate,
+ .initWithCompositor = ivi_layout_initWithCompositor
+};
--
1.8.3.1
Nobuhiko Tanibata
2014-05-20 04:29:40 UTC
Permalink
This protocol realizes following features,
- UI ready
- changing modes; tiling, side by side, full_screen, and random
- Give control a surface; workspace to be controlled by using ivi layout APIs
- Display/undisplay a surface; home contains sevaral workspaces to launch
application

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- squash Makefile to this patch

Changes for v3 and v4
- nothing. Version number aligned to the first patch

Changes for v5:
- rebase weston v1.5 branch
- apply review comments from mailing list

protocol/Makefile.am | 3 +-
protocol/ivi-hmi-controller.xml | 96 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 1 deletion(-)
create mode 100644 protocol/ivi-hmi-controller.xml

diff --git a/protocol/Makefile.am b/protocol/Makefile.am
index 9913f16..140aef5 100644
--- a/protocol/Makefile.am
+++ b/protocol/Makefile.am
@@ -9,7 +9,8 @@ protocol_sources = \
wayland-test.xml \
xdg-shell.xml \
scaler.xml \
- ivi-application.xml
+ ivi-application.xml \
+ ivi-hmi-controller.xml

if HAVE_XMLLINT
.PHONY: validate
diff --git a/protocol/ivi-hmi-controller.xml b/protocol/ivi-hmi-controller.xml
new file mode 100644
index 0000000..fd5ce2b
--- /dev/null
+++ b/protocol/ivi-hmi-controller.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ivi_hmi_controller">
+
+ <copyright>
+ Copyright (C) 2013 DENSO CORPORATION
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ </copyright>
+
+ <interface name="ivi_hmi_controller" version="1">
+ <description summary="set up and control IVI style UI"/>
+
+ <request name="UI_ready">
+ <description summary="inform the ready for drawing desktop." />
+ </request>
+
+ <request name="workspace_control">
+ <description summary="start controlling a surface by server">
+ Reference protocol to control a surface by server.
+ To control a surface by server, it gives seat to the server
+ to e.g. control Home screen. Home screen has several workspaces
+ to group launchers of wayland application. These workspaces
+ are drawn on a horizontally long surface to be controlled
+ by motion of input device. E.g. A motion from right to left
+ happens, the viewport of surface is controlled in the ivi-shell
+ by using ivi-layout. client can recognizes the end of controlling
+ by event "workspace_end_control".
+ </description>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ <arg name="serial" type="uint"/>
+ </request>
+
+ <enum name="layout_mode">
+ <entry name="tiling" value="0"/>
+ <entry name="side_by_side" value="1"/>
+ <entry name="full_screen" value="2"/>
+ <entry name="random" value="3" />
+ </enum>
+
+ <request name="switch_mode">
+ <description summary="request mode switch of application layout">
+ hmi-controller loaded to ivi-shall implements 4 types of layout
+ as a reference; tiling, side by side, full_screen, and random.
+ </description>
+ <arg name="layout_mode" type="uint"/>
+ </request>
+
+ <enum name="home">
+ <entry name="off" value="0"/>
+ <entry name="on" value="1"/>
+ </enum>
+
+ <request name="home">
+ <description summary="request displaying/undisplaying home screen">
+ home screen is a reference implementation of launcher to launch
+ wayland applications. The home screen has several workspaces to
+ group wayland applications. By defining the following keys in
+ weston.ini, user can add launcher icon to launch a wayland application
+ to a workspace.
+ [ivi-launcher]
+ workspace-id=0
+ : id of workspace to add a launcher
+ icon-id=4001
+ : ivi id of ivi_surface to draw a icon
+ icon=/home/user/review/build-ivi-shell/data/icon_ivi_flower.png
+ : path to icon image
+ path=/home/user/review/build-ivi-shell/weston-dnd
+ : path to wayland application
+ </description>
+ <arg name="home" type="uint"/>
+ </request>
+
+ <event name="workspace_end_control">
+ <description summary="notify controlling workspace end"/>
+ <arg name="is_controlled" type="int"/>
+ </event>
+
+ </interface>
+
+</protocol>
--
1.8.3.1
Nobuhiko Tanibata
2014-05-20 04:30:05 UTC
Permalink
The library is used to manage layout of surfaces/layers. Layout change is
triggered by ivi-hmi-controller protocol, ivi-hmi-controller.xml. A reference
how to use the protocol, see hmi-controller-homescreen.

In-Vehicle Infotainment system usually manage properties of surfaces/layers
by only a central component which decide where surfaces/layers shall be. This
reference show examples to implement the central component as a module of
weston.

Default Scene graph of UI is defined in hmi_controller_create. It consists of
- In the bottom, a base layer to group surfaces of background, panel,
and buttons
- Next, a application layer to show application surfaces.
- Workspace background layer to show a surface of background image.
- Workspace layer to show launcher to launch application with icons. Paths to
binary and icon are defined in weston.ini. The width of this layer is longer
than the size of screen because a workspace has several pages and is
controlled by motion of input.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- squash Makefile to this patch

Changes for v3 and v4
- nothing. Version number aligned to the first patch

Changes for v5:
- rebase weston v1.5 branch
- apply review comments from mailing list

Makefile.am | 20 +-
ivi-shell/.gitignore | 7 +
ivi-shell/hmi-controller.c | 1924 +++++++++++++++++++++++++++++++++++++++++
ivi-shell/ivi-layout-export.h | 18 +-
ivi-shell/ivi-layout.c | 28 +-
5 files changed, 1971 insertions(+), 26 deletions(-)
create mode 100644 ivi-shell/.gitignore
create mode 100644 ivi-shell/hmi-controller.c

diff --git a/Makefile.am b/Makefile.am
index e8bcb1b..1f75cc3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -704,7 +704,8 @@ if ENABLE_IVI_SHELL

module_LTLIBRARIES += \
$(ivi_shell) \
- $(ivi_layout)
+ $(ivi_layout) \
+ $(hmi_controller)

ivi_shell = ivi-shell.la
ivi_shell_la_LDFLAGS = -module -avoid-version
@@ -720,6 +721,7 @@ nodist_ivi_shell_la_SOURCES = \

BUILT_SOURCES += $(nodist_ivi_shell_la_SOURCES)

+
ivi_layout = ivi-layout.la
ivi_layout_la_LDFLAGS = -module -avoid-version
ivi_layout_la_LIBADD = $(COMPOSITOR_LIBS) $(IVI_SHELL_LIBS) libshared.la
@@ -734,6 +736,22 @@ nodist_ivi_layout_la_SOURCES = \

BUILT_SOURCES += $(nodist_ivi_layout_la_SOURCES)

+hmi_controller = hmi-controller.la
+hmi_controller_la_LDFLAGS = -module -avoid-version
+hmi_controller_la_LIBADD = $(CLIENT_LIBS) $(IVI_SHELL_LIBS) libshared-cairo.la
+hmi_controller_la_CFLAGS = $(GCC_CFLAGS) $(IVI_SHELL_CFLAGS)
+hmi_controller_la_SOURCES = \
+ ivi-shell/ivi-layout-export.h \
+ ivi-shell/hmi-controller.c
+nodist_hmi_controller_la_SOURCES = \
+ protocol/ivi-application-protocol.c \
+ protocol/ivi-application-client-protocol.h \
+ protocol/ivi-hmi-controller-protocol.c \
+ protocol/ivi-hmi-controller-client-protocol.h \
+ protocol/ivi-hmi-controller-server-protocol.h
+
+BUILT_SOURCES += $(nodist_hmi_controller_la_SOURCES)
+
endif


diff --git a/ivi-shell/.gitignore b/ivi-shell/.gitignore
new file mode 100644
index 0000000..9f31bfd
--- /dev/null
+++ b/ivi-shell/.gitignore
@@ -0,0 +1,7 @@
+ivi-application-client-protocol.h
+ivi-application-protocol.c
+ivi-application-server-protocol.h
+ivi-hmi-controller-client-protocol.h
+ivi-hmi-controller-protocol.c
+ivi-hmi-controller-server-protocol.h
+weston.ini
diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
new file mode 100644
index 0000000..6717990
--- /dev/null
+++ b/ivi-shell/hmi-controller.c
@@ -0,0 +1,1924 @@
+/*
+ * Copyright (C) 2014 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * A reference implementation how to use ivi-layout APIs in order to manage
+ * layout of surfaces/layers. Layout change is triggered by ivi-hmi-controller
+ * protocol, ivi-hmi-controller.xml. A reference how to use the protocol, see
+ * hmi-controller-homescreen.
+ *
+ * In-Vehicle Infotainment system usually manage properties of surfaces/layers
+ * by only a central component which decide where surfaces/layers shall be. This
+ * reference show examples to implement the central component as a module of weston.
+ *
+ * Default Scene graph of UI is defined in hmi_controller_create. It consists of
+ * - In the bottom, a base layer to group surfaces of background, panel,
+ * and buttons
+ * - Next, a application layer to show application surfaces.
+ * - Workspace background layer to show a surface of background image.
+ * - Workspace layer to show launcher to launch application with icons. Paths to
+ * binary and icon are defined in weston.ini. The width of this layer is longer
+ * than the size of screen because a workspace has several pages and is controlled
+ * by motion of input.
+ *
+ * TODO: animation method shall be refined
+ * TODO: support fade-in when UI is ready
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+#include <assert.h>
+#include <time.h>
+
+#include "ivi-layout-export.h"
+#include "ivi-hmi-controller-server-protocol.h"
+
+/*****************************************************************************
+ * structure, globals
+ ****************************************************************************/
+struct hmi_controller_layer {
+ struct ivi_layout_layer *ivilayer;
+ uint32_t id_layer;
+ int32_t x;
+ int32_t y;
+ uint32_t width;
+ uint32_t height;
+};
+
+struct link_layer {
+ struct ivi_layout_layer *layout_layer;
+ struct wl_list link;
+};
+
+struct link_animation {
+ struct hmi_controller_animation *animation;
+ struct wl_list link;
+};
+
+struct hmi_controller_animation;
+typedef void (*hmi_controller_animation_frame_func)(void *animation, uint32_t timestamp);
+typedef void (*hmi_controller_animation_frame_user_func)(void *animation);
+typedef void (*hmi_controller_animation_destroy_func)(struct hmi_controller_animation *animation);
+
+struct move_animation_user_data {
+ struct ivi_layout_layer* layer;
+ struct animation_set *anima_set;
+ struct hmi_controller *hmi_ctrl;
+};
+
+struct hmi_controller_animation {
+ void *user_data;
+ uint32_t time_start;
+ uint32_t is_done;
+ hmi_controller_animation_frame_func frame_func;
+ hmi_controller_animation_frame_user_func frame_user_func;
+ hmi_controller_animation_destroy_func destroy_func;
+};
+
+struct hmi_controller_animation_fade {
+ struct hmi_controller_animation base;
+ double start;
+ double end;
+ struct weston_spring spring;
+};
+
+struct hmi_controller_animation_move {
+ struct hmi_controller_animation base;
+ double pos;
+ double pos_start;
+ double pos_end;
+ double v0;
+ double a;
+ double time_end;
+};
+
+struct hmi_controller_fade {
+ uint32_t isFadeIn;
+ struct hmi_controller_animation_fade *animation;
+ struct animation_set *anima_set;
+ struct wl_list layer_list;
+};
+
+struct animation_set {
+ struct wl_event_source *event_source;
+ struct wl_list animation_list;
+};
+
+struct
+hmi_server_setting {
+ uint32_t base_layer_id;
+ uint32_t application_layer_id;
+ uint32_t workspace_background_layer_id;
+ uint32_t workspace_layer_id;
+ uint32_t panel_height;
+};
+
+struct hmi_controller
+{
+ struct hmi_server_setting *hmi_setting;
+ struct hmi_controller_layer base_layer;
+ struct hmi_controller_layer application_layer;
+ struct hmi_controller_layer workspace_background_layer;
+ struct hmi_controller_layer workspace_layer;
+ enum ivi_hmi_controller_layout_mode layout_mode;
+
+ struct animation_set *anima_set;
+ struct hmi_controller_fade workspace_fade;
+ struct hmi_controller_animation_move *workspace_swipe_animation;
+ int32_t workspace_count;
+ struct wl_array ui_widgets;
+ int32_t is_initialized;
+};
+
+struct launcher_info
+{
+ uint32_t surface_id;
+ uint32_t workspace_id;
+ uint32_t index;
+};
+
+/*****************************************************************************
+ * local functions
+ ****************************************************************************/
+static void *
+fail_on_null(void *p, size_t size, char* file, int32_t line)
+{
+ if (size && !p) {
+ fprintf(stderr, "%s(%d) %zd: out of memory\n", file, line, size);
+ exit(EXIT_FAILURE);
+ }
+
+ return p;
+}
+
+static void *
+mem_alloc(size_t size, char* file, int32_t line)
+{
+ return fail_on_null(calloc(1, size), size, file, line);
+}
+
+#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
+
+static int32_t
+is_surf_in_uiWidget(struct hmi_controller *hmi_ctrl,
+ struct ivi_layout_surface *ivisurf)
+{
+ uint32_t id = ivi_layout_getIdOfSurface(ivisurf);
+
+ uint32_t *ui_widget_id = NULL;
+ wl_array_for_each (ui_widget_id, &hmi_ctrl->ui_widgets) {
+ if (*ui_widget_id == id) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+compare_launcher_info(const void *lhs, const void *rhs)
+{
+ const struct launcher_info *left = (const struct launcher_info *)lhs;
+ const struct launcher_info *right = (const struct launcher_info *)rhs;
+
+ if (left->workspace_id < right->workspace_id) {
+ return -1;
+ }
+
+ if (left->workspace_id > right->workspace_id) {
+ return 1;
+ }
+
+ if (left->index < right->index) {
+ return -1;
+ }
+
+ if (left->index > right->index) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Internal methods called by mainly ivi_hmi_controller_switch_mode
+ * This reference shows 4 examples how to use ivi_layout APIs.
+ */
+static void
+mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
+ struct ivi_layout_surface **ppSurface,
+ uint32_t surface_length,
+ struct hmi_controller_layer *layer)
+{
+ const float surface_width = (float)layer->width * 0.25;
+ const float surface_height = (float)layer->height * 0.5;
+ int32_t surface_x = 0;
+ int32_t surface_y = 0;
+ struct ivi_layout_surface *ivisurf = NULL;
+ int32_t ret = 0;
+
+ uint32_t i = 0;
+ uint32_t num = 1;
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ if (num <= 8) {
+ if (num < 5) {
+ surface_x = (int32_t)((num - 1) * (surface_width));
+ surface_y = 0;
+ }
+ else {
+ surface_x = (int32_t)((num - 5) * (surface_width));
+ surface_y = (int32_t)surface_height;
+ }
+ ret = ivi_layout_surfaceSetDestinationRectangle(ivisurf, surface_x, surface_y,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ num++;
+ continue;
+ }
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 0);
+ assert(!ret);
+ }
+}
+
+static void
+mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
+ struct ivi_layout_surface **ppSurface,
+ uint32_t surface_length,
+ struct hmi_controller_layer *layer)
+{
+ uint32_t surface_width = layer->width / 2;
+ uint32_t surface_height = layer->height;
+ struct ivi_layout_surface *ivisurf = NULL;
+ int32_t ret = 0;
+
+ uint32_t i = 0;
+ uint32_t num = 1;
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ if (num == 1) {
+ ret = ivi_layout_surfaceSetDestinationRectangle(ivisurf, 0, 0,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ num++;
+ continue;
+ }
+ else if (num == 2) {
+ ret = ivi_layout_surfaceSetDestinationRectangle(ivisurf, surface_width, 0,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ num++;
+ continue;
+ }
+
+ ivi_layout_surfaceSetVisibility(ivisurf, 0);
+ assert(!ret);
+ }
+}
+
+static void
+mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
+ struct ivi_layout_surface **ppSurface,
+ uint32_t surface_length,
+ struct hmi_controller_layer *layer)
+{
+ const uint32_t surface_width = layer->width;
+ const uint32_t surface_height = layer->height;
+ struct ivi_layout_surface *ivisurf = NULL;
+ int32_t ret = 0;
+
+ uint32_t i = 0;
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ ret = ivi_layout_surfaceSetDestinationRectangle(ivisurf, 0, 0,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+ }
+}
+
+static void
+mode_random_replace(struct hmi_controller *hmi_ctrl,
+ struct ivi_layout_surface **ppSurface,
+ uint32_t surface_length,
+ struct hmi_controller_layer *layer)
+{
+ const uint32_t surface_width = (uint32_t)(layer->width * 0.25f);
+ const uint32_t surface_height = (uint32_t)(layer->height * 0.25f);
+ uint32_t surface_x = 0;
+ uint32_t surface_y = 0;
+ struct ivi_layout_surface *ivisurf = NULL;
+ int32_t ret = 0;
+
+ uint32_t i = 0;
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ surface_x = rand() % (layer->width - surface_width);
+ surface_y = rand() % (layer->height - surface_height);
+
+ ret = ivi_layout_surfaceSetDestinationRectangle(ivisurf, surface_x, surface_y,
+ surface_width, surface_height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+ }
+}
+
+static int32_t
+has_applicatipn_surface(struct hmi_controller *hmi_ctrl,
+ struct ivi_layout_surface **ppSurface,
+ uint32_t surface_length)
+{
+ struct ivi_layout_surface *ivisurf = NULL;
+ uint32_t i = 0;
+
+ for (i = 0; i < surface_length; i++) {
+ ivisurf = ppSurface[i];
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ continue;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Supports 4 example to layout of application surfaces;
+ * tiling, side by side, fullscreen, and random.
+ */
+static void
+switch_mode(struct hmi_controller *hmi_ctrl,
+ enum ivi_hmi_controller_layout_mode layout_mode)
+{
+ if (!hmi_ctrl->is_initialized) {
+ return;
+ }
+
+ struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
+ struct ivi_layout_surface **ppSurface = NULL;
+ uint32_t surface_length = 0;
+ int32_t ret = 0;
+
+ hmi_ctrl->layout_mode = layout_mode;
+
+ ret = ivi_layout_getSurfaces(&surface_length, &ppSurface);
+ assert(!ret);
+
+ if (!has_applicatipn_surface(hmi_ctrl, ppSurface, surface_length)) {
+ free(ppSurface);
+ ppSurface = NULL;
+ return;
+ }
+
+ switch (layout_mode) {
+ case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
+ mode_divided_into_tiling(hmi_ctrl, ppSurface, surface_length, layer);
+ break;
+ case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
+ mode_divided_into_sidebyside(hmi_ctrl, ppSurface, surface_length, layer);
+ break;
+ case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
+ mode_fullscreen_someone(hmi_ctrl, ppSurface, surface_length, layer);
+ break;
+ case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
+ mode_random_replace(hmi_ctrl, ppSurface, surface_length, layer);
+ break;
+ }
+
+ ivi_layout_commitChanges();
+
+ free(ppSurface);
+ ppSurface = NULL;
+
+ return;
+}
+
+/**
+ * Internal method for animation
+ */
+static void
+hmi_controller_animation_frame(
+ struct hmi_controller_animation *animation, uint32_t timestamp)
+{
+ if (0 == animation->time_start) {
+ animation->time_start = timestamp;
+ }
+
+ animation->frame_func(animation, timestamp);
+ animation->frame_user_func(animation);
+}
+
+static int
+animation_set_do_anima(void* data)
+{
+ struct animation_set *anima_set = data;
+ uint32_t fps = 30;
+
+ if (wl_list_empty(&anima_set->animation_list)) {
+ wl_event_source_timer_update(anima_set->event_source, 0);
+ return 1;
+ }
+
+ wl_event_source_timer_update(anima_set->event_source, 1000 / fps);
+
+ struct timespec timestamp = {0};
+ clock_gettime(CLOCK_MONOTONIC, &timestamp);
+ uint32_t msec = (1e+3 * timestamp.tv_sec + 1e-6 * timestamp.tv_nsec);
+
+ struct link_animation *link_animation = NULL;
+ struct link_animation *next = NULL;
+
+ wl_list_for_each_safe(link_animation, next, &anima_set->animation_list, link) {
+ hmi_controller_animation_frame(link_animation->animation, msec);
+ }
+
+ ivi_layout_commitChanges();
+ return 1;
+}
+
+static struct animation_set *
+animation_set_create(struct weston_compositor* ec)
+{
+ struct animation_set *anima_set = MEM_ALLOC(sizeof(*anima_set));
+
+ wl_list_init(&anima_set->animation_list);
+
+ struct wl_event_loop *loop = wl_display_get_event_loop(ec->wl_display);
+ anima_set->event_source = wl_event_loop_add_timer(loop, animation_set_do_anima, anima_set);
+ wl_event_source_timer_update(anima_set->event_source, 0);
+
+ return anima_set;
+}
+
+static void
+animation_set_add_animation(struct animation_set *anima_set,
+ struct hmi_controller_animation *anima)
+{
+ struct link_animation *link_anima = NULL;
+
+ link_anima = MEM_ALLOC(sizeof(*link_anima));
+ if (NULL == link_anima) {
+ return;
+ }
+
+ link_anima->animation = anima;
+ wl_list_insert(&anima_set->animation_list, &link_anima->link);
+ wl_event_source_timer_update(anima_set->event_source, 1);
+}
+
+static void
+animation_set_remove_animation(struct animation_set *anima_set,
+ struct hmi_controller_animation *anima)
+{
+ struct link_animation *link_animation = NULL;
+ struct link_animation *next = NULL;
+
+ wl_list_for_each_safe(link_animation, next, &anima_set->animation_list, link) {
+ if (link_animation->animation == anima) {
+ wl_list_remove(&link_animation->link);
+ free(link_animation);
+ break;
+ }
+ }
+}
+
+static void
+hmi_controller_animation_spring_frame(
+ struct hmi_controller_animation_fade *animation, uint32_t timestamp)
+{
+ if (0 == animation->spring.timestamp) {
+ animation->spring.timestamp = timestamp;
+ }
+
+ weston_spring_update(&animation->spring, timestamp);
+ animation->base.is_done = weston_spring_done(&animation->spring);
+}
+
+static void
+hmi_controller_animation_move_frame(
+ struct hmi_controller_animation_move *animation, uint32_t timestamp)
+{
+ double s = animation->pos_start;
+ double t = timestamp - animation->base.time_start;
+ double v0 = animation->v0;
+ double a = animation->a;
+ double time_end = animation->time_end;
+
+ if (time_end <= t) {
+ animation->pos = animation->pos_end;
+ animation->base.is_done = 1;
+ } else {
+ animation->pos = v0 * t + 0.5 * a * t * t + s;
+ }
+}
+
+static void
+hmi_controller_animation_destroy(struct hmi_controller_animation *animation)
+{
+ if (animation->destroy_func) {
+ animation->destroy_func(animation);
+ }
+
+ free(animation);
+}
+
+static void
+hmi_controller_fade_animation_destroy(struct hmi_controller_animation *animation)
+{
+ struct hmi_controller_fade *fade = animation->user_data;
+ animation_set_remove_animation(fade->anima_set, animation);
+ fade->animation = NULL;
+ animation->user_data = NULL;
+}
+
+static struct hmi_controller_animation_fade *
+hmi_controller_animation_fade_create(double start, double end, double k,
+ hmi_controller_animation_frame_user_func frame_user_func, void* user_data,
+ hmi_controller_animation_destroy_func destroy_func)
+{
+ struct hmi_controller_animation_fade* animation = MEM_ALLOC(sizeof(*animation));
+
+ animation->base.frame_user_func = frame_user_func;
+ animation->base.user_data = user_data;
+ animation->base.frame_func =
+ (hmi_controller_animation_frame_func)hmi_controller_animation_spring_frame;
+ animation->base.destroy_func = destroy_func;
+
+ animation->start = start;
+ animation->end = end;
+ weston_spring_init(&animation->spring, k, start, end);
+ animation->spring.friction = 1400;
+ animation->spring.previous = -(end - start) * 0.03;
+
+ return animation;
+}
+
+static struct hmi_controller_animation_move *
+hmi_controller_animation_move_create(
+ double pos_start, double pos_end, double v_start, double v_end,
+ hmi_controller_animation_frame_user_func frame_user_func, void* user_data,
+ hmi_controller_animation_destroy_func destroy_func)
+{
+ struct hmi_controller_animation_move* animation = MEM_ALLOC(sizeof(*animation));
+
+ animation->base.frame_user_func = frame_user_func;
+ animation->base.user_data = user_data;
+ animation->base.frame_func =
+ (hmi_controller_animation_frame_func)hmi_controller_animation_move_frame;
+ animation->base.destroy_func = destroy_func;
+
+ animation->pos_start = pos_start;
+ animation->pos_end = pos_end;
+ animation->v0 = v_start;
+ animation->pos = pos_start;
+
+ double dx = (pos_end - pos_start);
+
+ if (1e-3 < fabs(dx)) {
+ animation->a = 0.5 * (v_end * v_end - v_start * v_start) / dx;
+ if (1e-6 < fabs(animation->a)) {
+ animation->time_end = (v_end - v_start) / animation->a;
+
+ } else {
+ animation->a = 0;
+ animation->time_end = fabs(dx / animation->v0);
+ }
+
+ } else {
+ animation->time_end = 0;
+ }
+
+ return animation;
+}
+
+static double
+hmi_controller_animation_fade_alpha_get(struct hmi_controller_animation_fade* animation)
+{
+ if (animation->spring.current > 0.999) {
+ return 1.0;
+ } else if (animation->spring.current < 0.001 ) {
+ return 0.0;
+ } else {
+ return animation->spring.current;
+ }
+}
+
+static uint32_t
+hmi_controller_animation_is_done(struct hmi_controller_animation *animation)
+{
+ return animation->is_done;
+}
+
+static void
+hmi_controller_fade_update(struct hmi_controller_animation_fade *animation, double end)
+{
+ animation->spring.target = end;
+}
+
+static void
+hmi_controller_anima_fade_user_frame(struct hmi_controller_animation_fade *animation)
+{
+ double alpha = hmi_controller_animation_fade_alpha_get(animation);
+ alpha = wl_fixed_from_double(alpha);
+ struct hmi_controller_fade *fade = animation->base.user_data;
+ struct link_layer *linklayer = NULL;
+ int32_t is_done = hmi_controller_animation_is_done(&animation->base);
+ int32_t is_visible = !is_done || fade->isFadeIn;
+
+ wl_list_for_each(linklayer, &fade->layer_list, link) {
+ ivi_layout_layerSetOpacity(linklayer->layout_layer, alpha);
+ ivi_layout_layerSetVisibility(linklayer->layout_layer, is_visible);
+ }
+
+ if (is_done) {
+ hmi_controller_animation_destroy(&animation->base);
+ }
+}
+
+static void
+hmi_controller_anima_move_user_frame(struct hmi_controller_animation_move *animation)
+{
+ struct move_animation_user_data* user_data = animation->base.user_data;
+ struct ivi_layout_layer *layer = user_data->layer;
+ int32_t is_done = hmi_controller_animation_is_done(&animation->base);
+
+ int32_t pos[2] = {0};
+ ivi_layout_layerGetPosition(layer, pos);
+
+ pos[0] = (int32_t)animation->pos;
+ ivi_layout_layerSetPosition(layer, pos);
+
+ if (is_done) {
+ hmi_controller_animation_destroy(&animation->base);
+ }
+}
+
+static void
+hmi_controller_fade_run(uint32_t isFadeIn, struct hmi_controller_fade *fade)
+{
+ double tint = isFadeIn ? 1.0 : 0.0;
+ fade->isFadeIn = isFadeIn;
+
+ if (fade->animation) {
+ hmi_controller_fade_update(fade->animation, tint);
+ } else {
+ fade->animation = hmi_controller_animation_fade_create(
+ 1.0 - tint, tint, 300.0,
+ (hmi_controller_animation_frame_user_func)hmi_controller_anima_fade_user_frame,
+ fade, hmi_controller_fade_animation_destroy);
+
+ animation_set_add_animation(fade->anima_set, &fade->animation->base);
+ }
+}
+
+/**
+ * Internal method to create layer with hmi_controller_layer and add to a screen
+ */
+static void
+create_layer(struct ivi_layout_screen *iviscrn,
+ struct hmi_controller_layer *layer)
+{
+ int32_t ret = 0;
+
+ layer->ivilayer = ivi_layout_layerCreateWithDimension(layer->id_layer,
+ layer->width, layer->height);
+ assert(layer->ivilayer != NULL);
+
+ ret = ivi_layout_screenAddLayer(iviscrn, layer->ivilayer);
+ assert(!ret);
+
+ ret = ivi_layout_layerSetDestinationRectangle(layer->ivilayer, layer->x, layer->y,
+ layer->width, layer->height);
+ assert(!ret);
+
+ ret = ivi_layout_layerSetVisibility(layer->ivilayer, 1);
+ assert(!ret);
+}
+
+/**
+ * Internal set notification
+ */
+static void
+set_notification_create_surface(struct ivi_layout_surface *ivisurf,
+ void *userdata)
+{
+ struct hmi_controller* hmi_ctrl = userdata;
+ struct ivi_layout_layer *application_layer = hmi_ctrl->application_layer.ivilayer;
+ int32_t ret = 0;
+
+ /* skip ui widgets */
+ if (is_surf_in_uiWidget(hmi_ctrl, ivisurf)) {
+ return;
+ }
+
+ ret = ivi_layout_layerAddSurface(application_layer, ivisurf);
+ assert(!ret);
+}
+
+static void
+set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
+ void *userdata)
+{
+ (void)ivisurf;
+ struct hmi_controller* hmi_ctrl = userdata;
+ switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
+}
+
+static void
+set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
+ void *userdata)
+{
+ (void)ivisurf;
+ struct hmi_controller* hmi_ctrl = userdata;
+ switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
+}
+
+/**
+ * A hmi_controller used 4 layers to manage surfaces. The IDs of corresponding layer
+ * are defined in weston.ini. Default scene graph of layers are initialized in
+ * hmi_controller_create
+ */
+static struct hmi_server_setting *
+hmi_server_setting_create(void)
+{
+ struct hmi_server_setting* setting = MEM_ALLOC(sizeof(*setting));
+
+ struct weston_config *config = NULL;
+ config = weston_config_parse("weston.ini");
+
+ struct weston_config_section *shellSection = NULL;
+ shellSection = weston_config_get_section(config, "ivi-shell", NULL, NULL);
+
+ weston_config_section_get_uint(
+ shellSection, "base-layer-id", &setting->base_layer_id, 1000);
+
+ weston_config_section_get_uint(
+ shellSection, "workspace-background-layer-id", &setting->workspace_background_layer_id, 2000);
+
+ weston_config_section_get_uint(
+ shellSection, "workspace-layer-id", &setting->workspace_layer_id, 3000);
+
+ weston_config_section_get_uint(
+ shellSection, "application-layer-id", &setting->application_layer_id, 4000);
+
+ setting->panel_height = 70;
+
+ weston_config_destroy(config);
+
+ return setting;
+}
+
+/**
+ * This is a starting method called from module_init.
+ * This sets up scene graph of layers; base, application, workspace background,
+ * and workspace. These layers are created/added to screen in create_layer
+ *
+ * base: to group surfaces of panel and background
+ * application: to group surfaces of ivi_applications
+ * workspace background: to group a surface of background in workspace
+ * workspace: to group surfaces for launching ivi_applications
+ *
+ * Layers of workspace background and workspace is set to invisible at first.
+ * The properties of it is updated with animation when ivi_hmi_controller_home is
+ * requested.
+ */
+static struct hmi_controller *
+hmi_controller_create(struct weston_compositor *ec)
+{
+ struct ivi_layout_screen **ppScreen = NULL;
+ struct ivi_layout_screen *iviscrn = NULL;
+ uint32_t screen_length = 0;
+ uint32_t screen_width = 0;
+ uint32_t screen_height = 0;
+ int32_t ret = 0;
+ struct link_layer *tmp_link_layer = NULL;
+
+ struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
+ wl_array_init(&hmi_ctrl->ui_widgets);
+ hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
+ hmi_ctrl->hmi_setting = hmi_server_setting_create();
+
+ ivi_layout_getScreens(&screen_length, &ppScreen);
+
+ iviscrn = ppScreen[0];
+
+ ivi_layout_getScreenResolution(iviscrn, &screen_width, &screen_height);
+ assert(!ret);
+
+ /* init base layer*/
+ hmi_ctrl->base_layer.x = 0;
+ hmi_ctrl->base_layer.y = 0;
+ hmi_ctrl->base_layer.width = screen_width;
+ hmi_ctrl->base_layer.height = screen_height;
+ hmi_ctrl->base_layer.id_layer = hmi_ctrl->hmi_setting->base_layer_id;
+
+ create_layer(iviscrn, &hmi_ctrl->base_layer);
+
+ uint32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
+
+
+ /* init application layer */
+ hmi_ctrl->application_layer.x = 0;
+ hmi_ctrl->application_layer.y = 0;
+ hmi_ctrl->application_layer.width = screen_width;
+ hmi_ctrl->application_layer.height = screen_height - panel_height;
+ hmi_ctrl->application_layer.id_layer = hmi_ctrl->hmi_setting->application_layer_id;
+
+ create_layer(iviscrn, &hmi_ctrl->application_layer);
+
+ /* init workspace background layer */
+ hmi_ctrl->workspace_background_layer.x = 0;
+ hmi_ctrl->workspace_background_layer.y = 0;
+ hmi_ctrl->workspace_background_layer.width = screen_width;
+ hmi_ctrl->workspace_background_layer.height = screen_height - panel_height;
+
+ hmi_ctrl->workspace_background_layer.id_layer =
+ hmi_ctrl->hmi_setting->workspace_background_layer_id;
+
+ create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
+ ivi_layout_layerSetOpacity(hmi_ctrl->workspace_background_layer.ivilayer, 0);
+ ivi_layout_layerSetVisibility(hmi_ctrl->workspace_background_layer.ivilayer, 0);
+
+ /* init workspace layer */
+ hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
+ hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
+ hmi_ctrl->workspace_layer.width = hmi_ctrl->workspace_background_layer.width;
+ hmi_ctrl->workspace_layer.height = hmi_ctrl->workspace_background_layer.height;
+ hmi_ctrl->workspace_layer.id_layer = hmi_ctrl->hmi_setting->workspace_layer_id;
+
+ create_layer(iviscrn, &hmi_ctrl->workspace_layer);
+ ivi_layout_layerSetOpacity(hmi_ctrl->workspace_layer.ivilayer, 0);
+ ivi_layout_layerSetVisibility(hmi_ctrl->workspace_layer.ivilayer, 0);
+
+ /* set up animation to workspace background and workspace */
+ hmi_ctrl->anima_set = animation_set_create(ec);
+
+ wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
+ tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
+ tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
+ wl_list_insert(&hmi_ctrl->workspace_fade.layer_list, &tmp_link_layer->link);
+ tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
+ tmp_link_layer->layout_layer = hmi_ctrl->workspace_background_layer.ivilayer;
+ wl_list_insert(&hmi_ctrl->workspace_fade.layer_list, &tmp_link_layer->link);
+ hmi_ctrl->workspace_fade.anima_set = hmi_ctrl->anima_set;
+
+ ivi_layout_addNotificationCreateSurface(set_notification_create_surface, hmi_ctrl);
+ ivi_layout_addNotificationRemoveSurface(set_notification_remove_surface, hmi_ctrl);
+ ivi_layout_addNotificationConfigureSurface(set_notification_configure_surface, hmi_ctrl);
+
+ free(ppScreen);
+ ppScreen = NULL;
+
+ return hmi_ctrl;
+}
+
+/**
+ * Implementations of ivi-hmi-controller.xml
+ */
+
+/**
+ * A surface drawing background is identified by id_surface.
+ * Properties of the surface is set by using ivi_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * UI layer is used to add this surface.
+ */
+static void
+ivi_hmi_controller_set_background(struct wl_resource *resource,
+ uint32_t id_surface)
+
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
+ const uint32_t dstx = hmi_ctrl->application_layer.x;
+ const uint32_t dsty = hmi_ctrl->application_layer.y;
+ const uint32_t width = hmi_ctrl->application_layer.width;
+ const uint32_t height = hmi_ctrl->application_layer.height;
+ uint32_t ret = 0;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ ivisurf = ivi_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = ivi_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetDestinationRectangle(ivisurf,
+ dstx, dsty, width, height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ ivi_layout_commitChanges();
+}
+
+/**
+ * A surface drawing panel is identified by id_surface.
+ * Properties of the surface is set by using ivi_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * UI layer is used to add this surface.
+ */
+static void
+ivi_hmi_controller_set_panel(struct wl_resource *resource,
+ uint32_t id_surface)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
+ const uint32_t width = hmi_ctrl->base_layer.width;
+ uint32_t ret = 0;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ ivisurf = ivi_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = ivi_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+ uint32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
+ const uint32_t dstx = 0;
+ const uint32_t dsty = hmi_ctrl->base_layer.height - panel_height;
+
+ ret = ivi_layout_surfaceSetDestinationRectangle(
+ ivisurf, dstx, dsty, width, panel_height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ ivi_layout_commitChanges();
+}
+
+/**
+ * A surface drawing buttons in panel is identified by id_surface. It can set
+ * several buttons. Properties of the surface is set by using ivi_layout
+ * APIs according to the scene graph of UI defined in hmi_controller_create.
+ * Additionally, the position of it is shifted to right when new one is requested.
+ *
+ * UI layer is used to add these surfaces.
+ */
+static void
+ivi_hmi_controller_set_button(struct wl_resource *resource,
+ uint32_t id_surface, uint32_t number)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
+ const uint32_t width = 48;
+ const uint32_t height = 48;
+ uint32_t ret = 0;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ ivisurf = ivi_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = ivi_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+
+ uint32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
+
+ const uint32_t dstx = (60 * number) + 15;
+ const uint32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
+
+ ret = ivi_layout_surfaceSetDestinationRectangle(
+ ivisurf,dstx, dsty, width, height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ ivi_layout_commitChanges();
+}
+
+/**
+ * A surface drawing home button in panel is identified by id_surface.
+ * Properties of the surface is set by using ivi_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * UI layer is used to add these surfaces.
+ */
+static void
+ivi_hmi_controller_set_home_button(struct wl_resource *resource,
+ uint32_t id_surface)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
+ uint32_t ret = 0;
+ uint32_t size = 48;
+ uint32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
+ const uint32_t dstx = (hmi_ctrl->base_layer.width - size) / 2;
+ const uint32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ ivisurf = ivi_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = ivi_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetDestinationRectangle(
+ ivisurf, dstx, dsty, size, size);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ ivi_layout_commitChanges();
+ hmi_ctrl->is_initialized = 1;
+}
+
+/**
+ * A surface drawing background of workspace is identified by id_surface.
+ * Properties of the surface is set by using ivi_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * A layer of workspace_background is used to add this surface.
+ */
+static void
+ivi_hmi_controller_set_workspacebackground(struct wl_resource *resource,
+ uint32_t id_surface)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct ivi_layout_surface *ivisurf = NULL;
+ struct ivi_layout_layer *ivilayer = NULL;
+ ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
+
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = id_surface;
+
+ const uint32_t width = hmi_ctrl->workspace_background_layer.width;
+ const uint32_t height = hmi_ctrl->workspace_background_layer.height;
+ uint32_t ret = 0;
+
+ ivisurf = ivi_layout_getSurfaceFromId(id_surface);
+ assert(ivisurf != NULL);
+
+ ret = ivi_layout_layerAddSurface(ivilayer, ivisurf);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetDestinationRectangle(ivisurf,
+ 0, 0, width, height);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(ivisurf, 1);
+ assert(!ret);
+
+ ivi_layout_commitChanges();
+}
+
+/**
+ * A list of surfaces drawing launchers in workspace is identified by id_surfaces.
+ * Properties of the surface is set by using ivi_layout APIs according to
+ * the scene graph of UI defined in hmi_controller_create.
+ *
+ * The workspace can have several pages to group surfaces of launcher. Each call
+ * of this interface increments a number of page to add a group of surfaces
+ */
+static void
+ivi_hmi_controller_add_launchers(struct wl_resource *resource,
+ uint32_t icon_size)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
+ uint32_t minspace_x = 10;
+ uint32_t minspace_y = minspace_x;
+
+ uint32_t width = hmi_ctrl->workspace_layer.width;
+ uint32_t height = hmi_ctrl->workspace_layer.height;
+
+ uint32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
+ uint32_t space_x = (uint32_t)((width - x_count * icon_size) / (1.0 + x_count));
+ float fcell_size_x = icon_size + space_x;
+
+ uint32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
+ uint32_t space_y = (uint32_t)((height - y_count * icon_size) / (1.0 + y_count));
+ float fcell_size_y = icon_size + space_y;
+
+ if (0 == x_count) {
+ x_count = 1;
+ }
+
+ if (0 == y_count) {
+ y_count = 1;
+ }
+
+ struct weston_config *config = weston_config_parse("weston.ini");
+ if (!config) {
+ return;
+ }
+
+ struct weston_config_section *section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
+ if (!section) {
+ return;
+ }
+
+ const char *name = NULL;
+ int launcher_count = 0;
+ struct wl_array launchers;
+ wl_array_init(&launchers);
+
+ while (weston_config_next_section(config, &section, &name)) {
+ uint32_t surfaceid = 0;
+ uint32_t workspaceid = 0;
+ if (0 != strcmp(name, "ivi-launcher")) {
+ continue;
+ }
+
+ if (0 != weston_config_section_get_uint(section, "icon-id", &surfaceid, 0)) {
+ continue;
+ }
+
+ if (0 != weston_config_section_get_uint(section, "workspace-id", &workspaceid, 0)) {
+ continue;
+ }
+
+ struct launcher_info *info = wl_array_add(&launchers, sizeof(*info));
+
+ if (info) {
+ info->surface_id = surfaceid;
+ info->workspace_id = workspaceid;
+ info->index = launcher_count;
+ ++launcher_count;
+ }
+ }
+
+ qsort(launchers.data, launcher_count, sizeof(struct launcher_info), compare_launcher_info);
+
+ uint32_t nx = 0;
+ uint32_t ny = 0;
+ int32_t prev = -1;
+ struct launcher_info *data = NULL;
+ wl_array_for_each(data, &launchers)
+ {
+ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
+ sizeof(*add_surface_id));
+ *add_surface_id = data->surface_id;
+
+ if (0 > prev || (uint32_t)prev != data->workspace_id) {
+ nx = 0;
+ ny = 0;
+ prev = data->workspace_id;
+
+ if (0 <= prev) {
+ hmi_ctrl->workspace_count++;
+ }
+ }
+
+ if (y_count == ny) {
+ ny = 0;
+ hmi_ctrl->workspace_count++;
+ }
+
+ uint32_t x = (uint32_t)(nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x);
+ uint32_t y = (uint32_t)(ny * fcell_size_y + space_y) ;
+
+ struct ivi_layout_surface* layout_surface = NULL;
+ layout_surface = ivi_layout_getSurfaceFromId(data->surface_id);
+ assert(layout_surface);
+
+ uint32_t ret = 0;
+ ret = ivi_layout_layerAddSurface(layer, layout_surface);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetDestinationRectangle(
+ layout_surface, x, y, icon_size, icon_size);
+ assert(!ret);
+
+ ret = ivi_layout_surfaceSetVisibility(layout_surface, 1);
+ assert(!ret);
+
+ nx++;
+
+ if (x_count == nx) {
+ ny++;
+ nx = 0;
+ }
+ }
+
+ wl_array_release(&launchers);
+ weston_config_destroy(config);
+ ivi_layout_commitChanges();
+}
+
+static void
+ivi_hmi_controller_UI_ready(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct setting {
+ uint32_t background_id;
+ uint32_t panel_id;
+ uint32_t tiling_id;
+ uint32_t sidebyside_id;
+ uint32_t fullscreen_id;
+ uint32_t random_id;
+ uint32_t home_id;
+ uint32_t workspace_background_id;
+ };
+
+ struct config_command {
+ char *key;
+ void *dest;
+ };
+
+ struct weston_config *config = NULL;
+ struct weston_config_section *section = NULL;
+ struct setting dest;
+ int result = 0;
+ int i = 0;
+
+ const struct config_command uint_commands[] = {
+ { "background-id", &dest.background_id },
+ { "panel-id", &dest.panel_id },
+ { "tiling-id", &dest.tiling_id },
+ { "sidebyside-id", &dest.sidebyside_id },
+ { "fullscreen-id", &dest.fullscreen_id },
+ { "random-id", &dest.random_id },
+ { "home-id", &dest.home_id },
+ { "workspace-background-id", &dest.workspace_background_id },
+ { NULL, NULL }
+ };
+
+ config = weston_config_parse("weston.ini");
+ section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
+
+ for (i = 0; -1 != result; ++i)
+ {
+ const struct config_command *command = &uint_commands[i];
+
+ if (!command->key)
+ {
+ break;
+ }
+
+ if (weston_config_section_get_uint(
+ section, command->key, (uint32_t *)command->dest, 0) != 0)
+ {
+ result = -1;
+ }
+ }
+
+ if (-1 != result)
+ {
+ ivi_hmi_controller_set_background(resource, dest.background_id);
+ ivi_hmi_controller_set_panel(resource, dest.panel_id);
+ ivi_hmi_controller_set_button(resource, dest.tiling_id, 0);
+ ivi_hmi_controller_set_button(resource, dest.sidebyside_id, 1);
+ ivi_hmi_controller_set_button(resource, dest.fullscreen_id, 2);
+ ivi_hmi_controller_set_button(resource, dest.random_id, 3);
+ ivi_hmi_controller_set_home_button(resource, dest.home_id);
+ ivi_hmi_controller_set_workspacebackground(resource, dest.workspace_background_id);
+ }
+
+ weston_config_destroy(config);
+
+ ivi_hmi_controller_add_launchers(resource, 256);
+}
+
+/**
+ * Implementation of request and event of ivi_hmi_controller_workspace_control
+ * and controlling workspace.
+ *
+ * When motion of input is detected in a surface of workspace background,
+ * ivi_hmi_controller_workspace_control shall be invoked and to start controlling of
+ * workspace. The workspace has several pages to show several groups of applications.
+ * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
+ * according to motion. When motion finished, e.g. touch up detected, control is
+ * terminated and event:ivi_hmi_controller_workspace_control is notified.
+ */
+struct pointer_grab {
+ struct weston_pointer_grab grab;
+ struct ivi_layout_layer *layer;
+ struct wl_resource *resource;
+};
+
+struct touch_grab {
+ struct weston_touch_grab grab;
+ struct ivi_layout_layer *layer;
+ struct wl_resource *resource;
+};
+
+struct move_grab {
+ wl_fixed_t dst[2];
+ wl_fixed_t rgn[2][2];
+ double v[2];
+ struct timespec start_time;
+ struct timespec pre_time;
+ wl_fixed_t start_pos[2];
+ wl_fixed_t pos[2];
+ int32_t is_moved;
+};
+
+struct pointer_move_grab {
+ struct pointer_grab base;
+ struct move_grab move;
+};
+
+struct touch_move_grab {
+ struct touch_grab base;
+ struct move_grab move;
+ int32_t is_active;
+};
+
+static void
+pointer_grab_start(struct pointer_grab *grab,
+ struct ivi_layout_layer *layer,
+ const struct weston_pointer_grab_interface *interface,
+ struct weston_pointer *pointer)
+{
+ grab->grab.interface = interface;
+ grab->layer = layer;
+ weston_pointer_start_grab(pointer, &grab->grab);
+}
+
+static void
+touch_grab_start(struct touch_grab *grab,
+ struct ivi_layout_layer *layer,
+ const struct weston_touch_grab_interface *interface,
+ struct weston_touch* touch)
+{
+ grab->grab.interface = interface;
+ grab->layer = layer;
+ weston_touch_start_grab(touch, &grab->grab);
+}
+
+static int32_t
+range_val(int32_t val, int32_t min, int32_t max)
+{
+ if (val < min) {
+ return min;
+ }
+
+ if (max < val) {
+ return max;
+ }
+
+ return val;
+}
+
+static void
+hmi_controller_move_animation_destroy(struct hmi_controller_animation *animation)
+{
+ struct move_animation_user_data *user_data = animation->user_data;
+ if (animation == &user_data->hmi_ctrl->workspace_swipe_animation->base) {
+ user_data->hmi_ctrl->workspace_swipe_animation = NULL;
+ }
+
+ animation_set_remove_animation(user_data->anima_set, animation);
+ free(animation->user_data);
+ animation->user_data = NULL;
+}
+
+static void
+move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
+ wl_fixed_t grab_x, struct ivi_layout_layer *layer)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ int32_t width = (int32_t)hmi_ctrl->workspace_background_layer.width;
+
+ struct timespec time = {0};
+ clock_gettime(CLOCK_MONOTONIC, &time);
+
+ double grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
+ 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
+
+ double from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
+ 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
+
+ double pointer_v = move->v[0];
+
+ if (200 < from_motion_time) {
+ pointer_v = 0.0;
+ }
+
+ int32_t is_flick = grab_time < 400 &&
+ 0.4 < fabs(pointer_v);
+
+ int32_t pos[2] = {0};
+ ivi_layout_layerGetPosition(layer, pos);
+
+ int page_no = 0;
+
+ if (is_flick) {
+ int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
+ page_no = (-orgx + width / 2) / width;
+
+ if (pointer_v < 0.0) {
+ page_no++;
+ }else {
+ page_no--;
+ }
+ }else {
+ page_no = (-pos[0] + width / 2) / width;
+ }
+
+ page_no = range_val(page_no, 0, hmi_ctrl->workspace_count - 1);
+ double end_pos = -page_no * width;
+
+ double dst = fabs(end_pos - pos[0]);
+ double max_time = 0.5 * 1e+3;
+ double v = dst / max_time;
+
+ double vmin = 1000 * 1e-3;
+ if (v < vmin ) {
+ v = vmin;
+ }
+
+ double v0 = 0.0;
+ if (pos[0] < end_pos) {
+ v0 = v;
+ } else {
+ v0 = -v;
+ }
+
+ struct move_animation_user_data *animation_user_data = NULL;
+ animation_user_data = MEM_ALLOC(sizeof(*animation_user_data));
+ animation_user_data->layer = layer;
+ animation_user_data->anima_set = hmi_ctrl->anima_set;
+ animation_user_data->hmi_ctrl = hmi_ctrl;
+
+ struct hmi_controller_animation_move* animation = NULL;
+ animation = hmi_controller_animation_move_create(
+ pos[0], end_pos, v0, v0,
+ (hmi_controller_animation_frame_user_func)hmi_controller_anima_move_user_frame,
+ animation_user_data, hmi_controller_move_animation_destroy);
+
+ hmi_ctrl->workspace_swipe_animation = animation;
+ animation_set_add_animation(hmi_ctrl->anima_set, &animation->base);
+
+ ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
+}
+
+static void
+pointer_move_workspace_grab_end(struct pointer_grab *grab)
+{
+ struct pointer_move_grab *pnt_move_grab = (struct pointer_move_grab *) grab;
+ struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
+
+ move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
+ grab->grab.pointer->grab_x, layer);
+
+ weston_pointer_end_grab(grab->grab.pointer);
+}
+
+static void
+touch_move_workspace_grab_end(struct touch_grab *grab)
+{
+ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *) grab;
+ struct ivi_layout_layer *layer = tch_move_grab->base.layer;
+
+ move_workspace_grab_end(&tch_move_grab->move, grab->resource,
+ grab->grab.touch->grab_x, layer);
+
+ weston_touch_end_grab(grab->grab.touch);
+}
+
+static void
+pointer_noop_grab_focus(struct weston_pointer_grab *grab)
+{
+}
+
+static void
+move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
+{
+ struct timespec timestamp = {0};
+ clock_gettime(CLOCK_MONOTONIC, &timestamp);
+
+ double dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
+ 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
+
+ if (dt < 1e-6) {
+ dt = 1e-6;
+ }
+
+ move->pre_time = timestamp;
+
+ int32_t ii = 0;
+ for (ii = 0; ii < 2; ii++) {
+ wl_fixed_t prepos = move->pos[ii];
+ move->pos[ii] = pointer[ii] + move->dst[ii];
+
+ if (move->pos[ii] < move->rgn[0][ii]) {
+ move->pos[ii] = move->rgn[0][ii];
+ move->dst[ii] = move->pos[ii] - pointer[ii];
+ } else if (move->rgn[1][ii] < move->pos[ii]) {
+ move->pos[ii] = move->rgn[1][ii];
+ move->dst[ii] = move->pos[ii] - pointer[ii];
+ }
+
+ move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
+
+ if (!move->is_moved &&
+ 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii])) {
+ move->is_moved = 1;
+ }
+ }
+}
+
+static void
+layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos[2])
+{
+ int32_t layout_pos[2] = {0};
+ layout_pos[0] = wl_fixed_to_int(pos[0]);
+ layout_pos[1] = wl_fixed_to_int(pos[1]);
+ ivi_layout_layerSetPosition(layer, layout_pos);
+ ivi_layout_commitChanges();
+}
+
+static void
+pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
+ wl_fixed_t x, wl_fixed_t y)
+{
+ struct pointer_move_grab *pnt_move_grab = (struct pointer_move_grab *) grab;
+ wl_fixed_t pointer_pos[2] = {x, y};
+ move_grab_update(&pnt_move_grab->move, pointer_pos);
+ layer_set_pos(pnt_move_grab->base.layer, pnt_move_grab->move.pos);
+ weston_pointer_move(pnt_move_grab->base.grab.pointer, x, y);
+}
+
+static void
+touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
+ int touch_id, wl_fixed_t x, wl_fixed_t y)
+{
+ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *) grab;
+
+ if (!tch_move_grab->is_active) {
+ return;
+ }
+
+ wl_fixed_t pointer_pos[2] = {grab->touch->grab_x, grab->touch->grab_y};
+ move_grab_update(&tch_move_grab->move, pointer_pos);
+ layer_set_pos(tch_move_grab->base.layer, tch_move_grab->move.pos);
+}
+
+static void
+pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
+ uint32_t time, uint32_t button,
+ uint32_t state_w)
+{
+ if (BTN_LEFT == button &&
+ WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
+ struct pointer_grab *pg = (struct pointer_grab *)grab;
+ pointer_move_workspace_grab_end(pg);
+ free(grab);
+ }
+}
+
+static void
+touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
+ int touch_id, wl_fixed_t sx, wl_fixed_t sy)
+{
+}
+
+static void
+touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
+{
+ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
+
+ if (0 == touch_id) {
+ tch_move_grab->is_active = 0;
+ }
+
+ if (0 == grab->touch->num_tp) {
+ touch_move_workspace_grab_end(&tch_move_grab->base);
+ free(grab);
+ }
+}
+
+static void
+pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
+{
+ struct pointer_grab *pg = (struct pointer_grab *)grab;
+ pointer_move_workspace_grab_end(pg);
+ free(grab);
+}
+
+static void
+touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
+{
+ struct touch_grab *tg = (struct touch_grab *)grab;
+ touch_move_workspace_grab_end(tg);
+ free(grab);
+}
+
+static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
+ pointer_noop_grab_focus,
+ pointer_move_grab_motion,
+ pointer_move_workspace_grab_button,
+ pointer_move_workspace_grab_cancel
+};
+
+static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
+ touch_nope_grab_down,
+ touch_move_workspace_grab_up,
+ touch_move_grab_motion,
+ touch_move_workspace_grab_cancel
+};
+
+enum HMI_GRAB_DEVICE
+{
+ HMI_GRAB_DEVICE_NONE,
+ HMI_GRAB_DEVICE_POINTER,
+ HMI_GRAB_DEVICE_TOUCH
+};
+
+static enum HMI_GRAB_DEVICE
+get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
+{
+ if (seat->pointer &&
+ seat->pointer->focus &&
+ seat->pointer->button_count &&
+ seat->pointer->grab_serial == serial) {
+ return HMI_GRAB_DEVICE_POINTER;
+ }
+
+ if (seat->touch &&
+ seat->touch->focus &&
+ seat->touch->grab_serial) {
+ return HMI_GRAB_DEVICE_TOUCH;
+ }
+
+ return HMI_GRAB_DEVICE_NONE;
+}
+
+static void
+move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
+ wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
+ struct wl_resource* resource)
+{
+ clock_gettime(CLOCK_MONOTONIC, &move->start_time);
+ move->pre_time = move->start_time;
+ move->pos[0] = start_pos[0];
+ move->pos[1] = start_pos[1];
+ move->start_pos[0] = start_pos[0];
+ move->start_pos[1] = start_pos[1];
+ move->dst[0] = start_pos[0] - grab_pos[0];
+ move->dst[1] = start_pos[1] - grab_pos[1];
+ memcpy(move->rgn, rgn, sizeof(move->rgn));
+}
+
+static void
+move_grab_init_workspace(struct move_grab* move,
+ wl_fixed_t grab_x, wl_fixed_t grab_y,
+ struct wl_resource *resource)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
+ int32_t workspace_count = hmi_ctrl->workspace_count;
+ int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
+ int32_t layer_pos[2] = {0};
+ ivi_layout_layerGetPosition(layer, layer_pos);
+
+ wl_fixed_t start_pos[2] = {0};
+ start_pos[0] = wl_fixed_from_int(layer_pos[0]);
+ start_pos[1] = wl_fixed_from_int(layer_pos[1]);
+
+ wl_fixed_t rgn[2][2] = {{0}};
+ rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
+
+ rgn[0][1] = wl_fixed_from_int(0);
+ rgn[1][0] = wl_fixed_from_int(0);
+ rgn[1][1] = wl_fixed_from_int(0);
+
+ wl_fixed_t grab_pos[2] = {grab_x, grab_y};
+
+ move_grab_init(move, start_pos, grab_pos, rgn, resource);
+}
+
+static struct pointer_move_grab *
+create_workspace_pointer_move(struct weston_pointer *pointer, struct wl_resource* resource)
+{
+ struct pointer_move_grab *pnt_move_grab = MEM_ALLOC(sizeof(*pnt_move_grab));
+ pnt_move_grab->base.resource = resource;
+ move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x, pointer->grab_y, resource);
+ return pnt_move_grab;
+}
+
+static struct touch_move_grab *
+create_workspace_touch_move(struct weston_touch *touch, struct wl_resource* resource)
+{
+ struct touch_move_grab *tch_move_grab = MEM_ALLOC(sizeof(*tch_move_grab));
+ tch_move_grab->base.resource = resource;
+ tch_move_grab->is_active = 1;
+ move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,touch->grab_y, resource);
+ return tch_move_grab;
+}
+
+static void
+ivi_hmi_controller_workspace_control(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat_resource,
+ uint32_t serial)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+
+ if (hmi_ctrl->workspace_count < 2) {
+ return;
+ }
+
+ struct weston_seat* seat = wl_resource_get_user_data(seat_resource);
+ enum HMI_GRAB_DEVICE device = get_hmi_grab_device(seat, serial);
+
+ if (HMI_GRAB_DEVICE_POINTER != device &&
+ HMI_GRAB_DEVICE_TOUCH != device) {
+ return;
+ }
+
+ if (hmi_ctrl->workspace_swipe_animation) {
+ hmi_controller_animation_destroy(&hmi_ctrl->workspace_swipe_animation->base);
+ }
+
+ struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
+ struct pointer_move_grab *pnt_move_grab = NULL;
+ struct touch_move_grab *tch_move_grab = NULL;
+
+ switch (device) {
+ case HMI_GRAB_DEVICE_POINTER:
+ pnt_move_grab = create_workspace_pointer_move(seat->pointer, resource);
+
+ pointer_grab_start(
+ &pnt_move_grab->base, layer, &pointer_move_grab_workspace_interface,
+ seat->pointer);
+ break;
+
+ case HMI_GRAB_DEVICE_TOUCH:
+ tch_move_grab = create_workspace_touch_move(seat->touch, resource);
+
+ touch_grab_start(
+ &tch_move_grab->base, layer, &touch_move_grab_workspace_interface,
+ seat->touch);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * Implementation of switch_mode
+ */
+static void
+ivi_hmi_controller_switch_mode(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t layout_mode)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+ switch_mode(hmi_ctrl, layout_mode);
+}
+
+/**
+ * Implementation of on/off displaying workspace and workspace background layers.
+ */
+static void
+ivi_hmi_controller_home(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t home)
+{
+ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
+
+ if ((IVI_HMI_CONTROLLER_HOME_ON == home && !hmi_ctrl->workspace_fade.isFadeIn) ||
+ (IVI_HMI_CONTROLLER_HOME_OFF == home && hmi_ctrl->workspace_fade.isFadeIn)) {
+
+ uint32_t isFadeIn = !hmi_ctrl->workspace_fade.isFadeIn;
+ hmi_controller_fade_run(isFadeIn, &hmi_ctrl->workspace_fade);
+ }
+}
+
+/**
+ * binding ivi-hmi-controller implementation
+ */
+static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
+ ivi_hmi_controller_UI_ready,
+ ivi_hmi_controller_workspace_control,
+ ivi_hmi_controller_switch_mode,
+ ivi_hmi_controller_home
+};
+
+static void
+unbind_hmi_controller(struct wl_resource *resource)
+{
+}
+
+static void
+bind_hmi_controller(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct wl_resource *resource = NULL;
+
+ resource = wl_resource_create(
+ client, &ivi_hmi_controller_interface, 1, id);
+
+ wl_resource_set_implementation(
+ resource, &ivi_hmi_controller_implementation,
+ data, unbind_hmi_controller);
+}
+
+static void
+launch_hmi_client(void *data)
+{
+ /*Nothing to do here*/
+}
+
+/*****************************************************************************
+ * exported functions
+ ****************************************************************************/
+
+WL_EXPORT int
+module_init(struct weston_compositor *ec,
+ int *argc, char *argv[])
+{
+ struct hmi_controller *hmi_ctrl = hmi_controller_create(ec);
+
+ if (wl_global_create(ec->wl_display,
+ &ivi_hmi_controller_interface, 1,
+ hmi_ctrl, bind_hmi_controller) == NULL) {
+ return -1;
+ }
+
+ struct wl_event_loop *loop = wl_display_get_event_loop(ec->wl_display);
+ wl_event_loop_add_idle(loop, launch_hmi_client, ec);
+
+ return 0;
+}
diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h
index 0f95f53..9784cf3 100644
--- a/ivi-shell/ivi-layout-export.h
+++ b/ivi-shell/ivi-layout-export.h
@@ -106,10 +106,6 @@ struct ivi_layout_LayerProperties
struct ivi_layout_layer;
struct ivi_layout_screen;

-typedef struct ivi_layout_surface* ivi_layout_surface_ptr;
-typedef struct ivi_layout_layer* ivi_layout_layer_ptr;
-typedef struct ivi_layout_screen* ivi_layout_screen_ptr;
-
enum ivi_layout_notification_mask {
IVI_NOTIFICATION_NONE = 0,
IVI_NOTIFICATION_OPACITY = (1 << 1),
@@ -393,7 +389,7 @@ ivi_layout_getNumberOfHardwareLayers(uint32_t id_screen,
* \return -1 if the method call was failed
*/
int32_t
-ivi_layout_getScreens(uint32_t *pLength, ivi_layout_screen_ptr **ppArray);
+ivi_layout_getScreens(uint32_t *pLength, struct ivi_layout_screen ***ppArray);

/**
* \brief Get the screens under the given layer
@@ -404,7 +400,7 @@ ivi_layout_getScreens(uint32_t *pLength, ivi_layout_screen_ptr **ppArray);
int32_t
ivi_layout_getScreensUnderLayer(struct ivi_layout_layer *ivilayer,
uint32_t *pLength,
- ivi_layout_screen_ptr **ppArray);
+ struct ivi_layout_screen ***ppArray);

/**
* \brief Get all Layers which are currently registered and managed by the services
@@ -413,7 +409,7 @@ ivi_layout_getScreensUnderLayer(struct ivi_layout_layer *ivilayer,
* \return -1 if the method call was failed
*/
int32_t
-ivi_layout_getLayers(uint32_t *pLength, ivi_layout_layer_ptr **ppArray);
+ivi_layout_getLayers(uint32_t *pLength, struct ivi_layout_layer ***ppArray);

/**
* \brief Get all Layers of the given screen
@@ -424,7 +420,7 @@ ivi_layout_getLayers(uint32_t *pLength, ivi_layout_layer_ptr **ppArray);
int32_t
ivi_layout_getLayersOnScreen(struct ivi_layout_screen *iviscrn,
uint32_t *pLength,
- ivi_layout_layer_ptr **ppArray);
+ struct ivi_layout_layer ***ppArray);

/**
* \brief Get all Layers under the given surface
@@ -435,7 +431,7 @@ ivi_layout_getLayersOnScreen(struct ivi_layout_screen *iviscrn,
int32_t
ivi_layout_getLayersUnderSurface(struct ivi_layout_surface *ivisurf,
uint32_t *pLength,
- ivi_layout_layer_ptr **ppArray);
+ struct ivi_layout_layer ***ppArray);

/**
* \brief Get all Surfaces which are currently registered and managed by the services
@@ -444,7 +440,7 @@ ivi_layout_getLayersUnderSurface(struct ivi_layout_surface *ivisurf,
* \return -1 if the method call was failed
*/
int32_t
-ivi_layout_getSurfaces(uint32_t *pLength, ivi_layout_surface_ptr **ppArray);
+ivi_layout_getSurfaces(uint32_t *pLength, struct ivi_layout_surface ***ppArray);

/**
* \brief Get all Surfaces which are currently registered to a given layer and are managed by the services
@@ -455,7 +451,7 @@ ivi_layout_getSurfaces(uint32_t *pLength, ivi_layout_surface_ptr **ppArray);
int32_t
ivi_layout_getSurfacesOnLayer(struct ivi_layout_layer *ivilayer,
uint32_t *pLength,
- ivi_layout_surface_ptr **ppArray);
+ struct ivi_layout_surface ***ppArray);

/**
* \brief Create a layer which should be managed by the service
diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c
index 68f9b52..41b2b3b 100644
--- a/ivi-shell/ivi-layout.c
+++ b/ivi-shell/ivi-layout.c
@@ -1376,7 +1376,7 @@ ivi_layout_getNumberOfHardwareLayers(uint32_t id_screen,
}

WL_EXPORT int32_t
-ivi_layout_getScreens(uint32_t *pLength, ivi_layout_screen_ptr **ppArray)
+ivi_layout_getScreens(uint32_t *pLength, struct ivi_layout_screen ***ppArray)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_screen *iviscrn = NULL;
@@ -1392,7 +1392,7 @@ ivi_layout_getScreens(uint32_t *pLength, ivi_layout_screen_ptr **ppArray)

if (length != 0){
/* the Array must be free by module which called this function */
- *ppArray = calloc(length, sizeof(ivi_layout_screen_ptr));
+ *ppArray = calloc(length, sizeof(struct ivi_layout_screen *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return -1;
@@ -1411,7 +1411,7 @@ ivi_layout_getScreens(uint32_t *pLength, ivi_layout_screen_ptr **ppArray)
WL_EXPORT int32_t
ivi_layout_getScreensUnderLayer(struct ivi_layout_layer *ivilayer,
uint32_t *pLength,
- ivi_layout_screen_ptr **ppArray)
+ struct ivi_layout_screen ***ppArray)
{
struct link_screen *link_scrn = NULL;
uint32_t length = 0;
@@ -1426,7 +1426,7 @@ ivi_layout_getScreensUnderLayer(struct ivi_layout_layer *ivilayer,

if (length != 0){
/* the Array must be free by module which called this function */
- *ppArray = calloc(length, sizeof(ivi_layout_screen_ptr));
+ *ppArray = calloc(length, sizeof(struct ivi_layout_screen *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return -1;
@@ -1443,7 +1443,7 @@ ivi_layout_getScreensUnderLayer(struct ivi_layout_layer *ivilayer,
}

WL_EXPORT int32_t
-ivi_layout_getLayers(uint32_t *pLength, ivi_layout_layer_ptr **ppArray)
+ivi_layout_getLayers(uint32_t *pLength, struct ivi_layout_layer ***ppArray)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_layer *ivilayer = NULL;
@@ -1459,7 +1459,7 @@ ivi_layout_getLayers(uint32_t *pLength, ivi_layout_layer_ptr **ppArray)

if (length != 0){
/* the Array must be free by module which called this function */
- *ppArray = calloc(length, sizeof(ivi_layout_layer_ptr));
+ *ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return -1;
@@ -1478,7 +1478,7 @@ ivi_layout_getLayers(uint32_t *pLength, ivi_layout_layer_ptr **ppArray)
WL_EXPORT int32_t
ivi_layout_getLayersOnScreen(struct ivi_layout_screen *iviscrn,
uint32_t *pLength,
- ivi_layout_layer_ptr **ppArray)
+ struct ivi_layout_layer ***ppArray)
{
struct ivi_layout_layer *ivilayer = NULL;
uint32_t length = 0;
@@ -1493,7 +1493,7 @@ ivi_layout_getLayersOnScreen(struct ivi_layout_screen *iviscrn,

if (length != 0){
/* the Array must be free by module which called this function */
- *ppArray = calloc(length, sizeof(ivi_layout_layer_ptr));
+ *ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return -1;
@@ -1512,7 +1512,7 @@ ivi_layout_getLayersOnScreen(struct ivi_layout_screen *iviscrn,
WL_EXPORT int32_t
ivi_layout_getLayersUnderSurface(struct ivi_layout_surface *ivisurf,
uint32_t *pLength,
- ivi_layout_layer_ptr **ppArray)
+ struct ivi_layout_layer ***ppArray)
{
struct link_layer *link_layer = NULL;
uint32_t length = 0;
@@ -1527,7 +1527,7 @@ ivi_layout_getLayersUnderSurface(struct ivi_layout_surface *ivisurf,

if (length != 0){
/* the Array must be free by module which called this function */
- *ppArray = calloc(length, sizeof(ivi_layout_layer_ptr));
+ *ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return -1;
@@ -1544,7 +1544,7 @@ ivi_layout_getLayersUnderSurface(struct ivi_layout_surface *ivisurf,
}

WL_EXPORT int32_t
-ivi_layout_getSurfaces(uint32_t *pLength, ivi_layout_surface_ptr **ppArray)
+ivi_layout_getSurfaces(uint32_t *pLength, struct ivi_layout_surface ***ppArray)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_surface *ivisurf = NULL;
@@ -1560,7 +1560,7 @@ ivi_layout_getSurfaces(uint32_t *pLength, ivi_layout_surface_ptr **ppArray)

if (length != 0){
/* the Array must be free by module which called this function */
- *ppArray = calloc(length, sizeof(ivi_layout_surface_ptr));
+ *ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return -1;
@@ -1579,7 +1579,7 @@ ivi_layout_getSurfaces(uint32_t *pLength, ivi_layout_surface_ptr **ppArray)
WL_EXPORT int32_t
ivi_layout_getSurfacesOnLayer(struct ivi_layout_layer *ivilayer,
uint32_t *pLength,
- ivi_layout_surface_ptr **ppArray)
+ struct ivi_layout_surface ***ppArray)
{
struct ivi_layout_surface *ivisurf = NULL;
uint32_t length = 0;
@@ -1594,7 +1594,7 @@ ivi_layout_getSurfacesOnLayer(struct ivi_layout_layer *ivilayer,

if (length != 0) {
/* the Array must be free by module which called this function */
- *ppArray = calloc(length, sizeof(ivi_layout_surface_ptr));
+ *ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
if (*ppArray == NULL) {
weston_log("fails to allocate memory\n");
return -1;
--
1.8.3.1
Nobuhiko Tanibata
2014-05-20 04:30:27 UTC
Permalink
This is launched from hmi-controller by launch_hmi_client_process and invoke a
client process.

The basic flow is as followed,
1/ process invoked
2/ read configuration from weston.ini.
3/ draw png file to surface according to configuration of weston.ini
4/ all parts of UI are ready. request "UI_ready" to draw UI.
5/ Enter event loop
6/ If a surface receives touch/pointer event, followings are invoked according
to type of event and surface
6-1/ If a surface to launch ivi_application receive touch up, it execs
ivi-application configured in weston.ini.
6-2/ If a surface to switch layout mode receive touch up, it sends a request,
ivi_hmi_controller_switch_mode, to hmi-controller.
6-3/ If a surface to show workspace having launchers, it sends a request,
ivi_hmi_controller_home, to hmi-controller.
6-4/ If touch down events happens in workspace,
ivi_hmi_controller_workspace_control is sent to slide workspace.
When control finished, event: ivi_hmi_controller_workspace_end_control
is received.

Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA at xddp.denso.co.jp>
---

Changes for v2:
- squash Makefile to this patc