From f67d989f4b5e1ffd7e6cc562bf6065917b748342 Mon Sep 17 00:00:00 2001 From: Nobuhiko Tanibata Date: Tue, 6 May 2014 17:25:31 +0900 Subject: [PATCH 03/15] ivi-shell: add IVI layout APIs - ivi-layout.so - introduces ivi-layout-export.h, ivi-layout.[ch] 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 ivi-layout: fix calculation of view scale. Signed-off-by: Nobuhiko Tanibata -------------------------------------------------------- ivi-shell/ivi-layout.[ch] from transition animation -------------------------------------------------------- ivi-shell/ivi-layout-export.h from transition animation -------------------------------------------------------- ivi-shell/ivi-layout-private.h from transition animation -------------------------------------------------------- ivi-shell: Add IVI layout APIs - ivi_layout_surfaceGetWestonSurface - ivi_layout_surfaceGetSize These are used by screenshot APIs. Signed-off-by: Nobuhiko Tanibata ------------------------------------------------------- update for configure support Signed-off-by: Nobuhiko Tanibata ------------------------------------------------------ ivi-shell: transition animation support - introduces ivi-shell/ivi-layout-transition.[ch] interpolate animation when an atribute of surface is changed by commitChanges. ----------------------------------------------------------- update for configure support for transition animation Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Insert a space between "void" and "(*". > > In all function pointer type definitions, need a space between "void" > > and "(*". > [ntanibata] I will fix it. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Define return type. > > Hm, the return type is unsigned, so -1 makes little sense. Should > > there > > be something like #define IVI_INVALID_ID 0xffffffff and the use > > that? > [ntanibata] I agree. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Delete unused APIs > What is color? An array? How many bits per channel? > What if the output or buffer is at different bit depth? > [ntanibata] This is not valid. I will remove. > What are capabilities? > [ntanibata] This is not valid now. I will remove. > What is a layer type? > [ntanibata] This is not valid now. I will remove. > Unimplemented... how would you use this? > How would you set the content? > [ntanibata] This is not valid now. I will remove. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: remove commented-out code Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Delete input acceptance function. > > Is this really necessary, when you could be forcing the input region > > of > > weston_surface? What are 'devices' and... > > > > Oh, I see that this function is not actually implemented. You should > > remove > > all functions you do not implement. You can add the implementations > > later, > > and if you need the stubs to be able to test non-upstream code, you > > can > > keep the stubs in your own repository. > > > [ntanibata] I agree. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: layout APIs header, clean up public and private ones in two headers, ivi-layout-export/private.h > b40fdf4 ivi-shell: add IVI layout APIs > > Header rearrangements? > What are the API stability guarantees? > New title: "ivi-shell: add ivi-layout.so module and API" Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Changed stdbool from uint32_t > Supposedly visibility is a boolean? Non-zero means visible? > [ntanibata] It should be a Boolean. I will fix it. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Change the return-type of APIs to void if it had not used. > > It's kind of strange to see this sort of function being able to > > return > > failure. How could it reasonably fail? > > > > Looking at your implementation, it cannot fail, unless the caller > > made > > a mistake. It is worth returning a failure only if the called can > > sensibly > > react to or recover from it. > > > > Couldn't this (and all other remove functions) just return void? > > > > You can still do the sanity check in the code and log an error, but > > I > don't > > see value in returning the error from the function. Is there some > > value? > > > [ntanibata] I will change it to void. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- Change return-type of getter of properties APIs to const properties pointer. > > Any particular reason to return a copy, rather than a const pointer to > > the original? > [ntanibata] I will check. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Return the requested value in the return value. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Change type of orientation value int32_t to wl_output_transform. > > > > What is 'orientation'? enum wl_output_transform? > > > [ntanibata] rotate surface/layer with 0,90,180,270 degree. > > > > Yeah, I guessed that much, but what is the actual API here? :-) > > The values from enum wl_output_transform? > [ntanibata] they are from here. However, it should use enum > defined in Weston. I will fix it. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Delete functions of Keyboard focus. > > Keyboard focus of which weston_seat? How do you handle multiple > > weston_seats? > [ntanibata] This would be discuss later with patch of src/input.c. > For the time being, this will be removed. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Replace allocation check assert to if-statement. > > Heh, considering your usual paranoid pointer checks, using an assert > > here is surprising. ;-) > > > > I think in Weston we are accustomed to check the return value from > > malloc() and propagate the failure, even though it usually is in > > vain. > > > > assert()s should be reserved for programmer errors. > [ntanibata] I see. I will fix. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Delete needless memory allocation. > > Just allocate it from stack instead? > [ntanibata] I will fix it. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Use the weston_config that has already been created. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Output log when mamory allocation fails. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Delete cursor check. > > > > What is this about? > > > > Why would you remove the cursor_layer? > > > > Also, there is a default cursor theme if nothing is set in > > > > weston.ini. > > > [ntanibata] I think I should add comments clearly. > > > If cursor-theme is not set, I want to disable showing cursor > > > because cursor is not mandatory on ivi system e.g with touch > > > panel. > > > So I call wl_list_remove. > > > > But a cursor theme has nothing to do whether a cursor will be shown. > > If no theme is set, a default theme is used (and if that does not > > exist, a built-in theme from libwayland-cursor gets used). So there > > is always some theme, regardless of settings. > > > > A cursor will be shown, if the compositor has a wl_pointer device (a > > mouse). > > If there are no wl_pointer devices, there are also no cursors. > > That is how Weston works already. > [ntanibata] Oh, I see. This feature fix may use case. So I will remove > this code. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Fix ivi_layout_layerGetDimension Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Change int type from array type > Just one value? Or is it supposed to be an array of two values? > [ntanibata] It is an array two values. Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Delete unsupported APIs. > > Why would an external module want to know? It cannot really do > > anything > > with that information, can it? > > > > Handling hardware overlays is an internal detail of a Weston > > backend, and > > deliberately not exposed to clients, and not even to outside of the > > backend really. > [ntanibata] I will remote this API. This is just a history from Layer > manager Signed-off-by: Nobuhiko Tanibata ----------------------------------------------------------- ivi-shell: Modification of function name > "identifier"? > [ntanibata] right. I will fix it. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Fix comment out message > Twice? > [ntanibata] Oh, I will remove one. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Add function header comments. > > What is this for really? The implementation looks suspiciously > > broken, > > depending on how it is supposed to be used. > [ntanibata] If this is not used, I will remove. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Fix ivi_layout_surfaceSetPosition. Change int type from array type > Again, array of two or? > [ntanibata] I will fix. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- Add comments: what happens when commitchange is called during transition animation in comment of ivi-layout.c Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Delete ivi_layout_surface_pixelformat > Does this pixel format enumeration come from somewhere, or was it > invented here? Or are you removing it with the unsupported/unused features? > [ntanibata]Yes, I will remove them. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Change quoted_printable_encode form camelcase > Is the style here, that all internal and Weston core facing things are > named with underscores, and all ivi-layout public API is in CamelCase? > [ntanibata] I will change them to underscores to avoid CamelCase. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- add FIXME at calling clock_gettime Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Replace list_thing with thing_list. > > We'd prefer naming it as thing_list, not list_thing. Like in English > > you can have a "note list" meaning a "list of notes", while "list > > note" > > sounds like it is one note about a list. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Declare variable in the beginning of a block. > > Declarations mixed up with code. Our style has declarations only in > > the beginning of a block. > [ntanibata] I will fix it. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout.c, clean-up definition of valueable in the middle function. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout.c, remove #if 0 Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout-transition.c, clean-up definition of valueable in the middle Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout-transition.c, remove code commented out Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout, modify comments, surface/layer/screen -> ivi_* Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Delete duplicated of definition. > > > > Looks identical to enum ivi_layout_transition_type, do you > > > > really need another? > > > [ntanibata] Question: Do you mean why there are many types? > > > > Why define ivi_layout_inner_transition_type, when > > ivi_layout_transition_type is already the same down to the actual > > values, if I'm not mistaken? > > > > Why not just use ivi_layout_transition_type everywhere? > [ntanibata] Oh, I see "inner". I will fix them. I jumped the gun:) Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout-export/private.h, reorgenize two interface from private to export because it is used by hmi-controller.c Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Use error-code defined in ivi-application-protocol. > > You also need to add the two error codes into ivi-application > > interface and use those instead of WL_DISPLAY_ERROR_INVALID_OBJECT. > [ntanibata] I will fix this according to two error codes. > > > > Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Amend wrong comments regarding return values: Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Fix transition bug on visibility change. This is embeded during cleaning up code. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Qualify const modifier to readonly argument. This is embded during cleaning up code before. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Fix invalid type. > prop->opacity = wlfixedfrom_double(1.0); > What? 'opacity' is a float, isn't it? Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell:ivi-layout.c Change type of calculatable variables to signed from unsigned > FWIW, if you are going to do calculations with these variables, they > should be signed. If you mix unsigned and signed variables in > calculations, the result is probably not what you expect in all cases. > This is just a reminder for you, that you might want to change these in the future. > Weston core categorically uses signed variables for anything that is > involved in calculations, even if negative values would not make any > sense for a particular variable. > Counters (that may wrap around) are of course better stored as unsigned. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- Makefile.am: clean up Makefile.am with FR3 for ivi-layout Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- configure.ac: remove checking module cairo. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout-export.h, remove unused member of structure. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout-transition, remove wl_event_source_timer_update because The timer is already disarmed when you create it. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout-export.h, add an explanation of what kind of stability guarantees this API and ABI should have. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Move functions that are not used by other to private.h from export.h. > +WL_EXPORT int32_t +ivi_layout_surface_get_dimension(struct > ivi_layout_surface ivisurf, + int32_t dest_width, int32_t +*dest_height) > Does this function need to be WL_EXPORT? > hmi-controller does not use it, and it is exposed to ivi-shell.so via > struct ivi_layout_interface. For the time being, there are some APIs which is not used by hmi-controller.c. but it is used by ivi-controller.so maintained by another project. I will add reference implementation for them later in hmi-controller.c Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-layout: ivi-layout-export.h remove type of ivi_layout_layer_properties Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: Rename confusing functions > .oO( That looks strange, it's returning either 0 or 1 as an identifier. > Maybe this has nothing to do with identifiers... ) This callback is to detect whether transition happens or not. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout-private/export.h, move struct ivi_layout_interface declarations from > ivi-layout-export.h into ivi-layout-private.h Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout.c, Remove casts to (void) > I don't think we need these casts. The warning about unused arguments is disabled, isn't it? > You should be able to remove casts to (void) from all places. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-layout: private.h, remove WL_EXPORT definition of ivi_layout_interface Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-layout: remove ivi_layout_surface_set_native_content. There are two use case to - create ivi_surface without wl_surface to set property in advanced - keep property per ID during deletion of ivi_surface. This is supported later. For the time being, remove this function. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-layout: Fix invalid memory read/write. correct destruction methods Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-layout: code style clean up Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-layout: revert destruction method to re-organize them. This commit is a target of this revert. https://github.com/ntanibata/weston-ivi-shell/commit/f097ccf90a12efad954228f2534a4cad8f578d19 Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-layout: remove unused function. This was called from ivi-shell. However it is not called anymore after code clean up. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-shell: ivi-layout.c, Remove all configure event on specified surface. Signed-off-by: Nobuhiko Tanibata ---------------------------------------------------------- ivi-layout.c: remove unneeded casts Also a couple of whitespace fixes. ivi-layout.c: reflow long lines ---------------------------------------------------------- ivi-layout.c: simplify add_link_to_surface() There is a way to make this function even simpler. If you guarantee, that it is always legal to call wl_list_remove() on the link, this function could literally be just: wl_list_remove(&link_layer->link_to_layer); wl_list_insert(&ivilayer->link_to_surface, &link_layer->link_to_layer); You would go from an O(n) operation to O(1) operation! --- Makefile.am | 20 + configure.ac | 9 + ivi-shell/ivi-layout-export.h | 689 +++++++++ ivi-shell/ivi-layout-private.h | 319 +++++ ivi-shell/ivi-layout-transition.c | 1111 +++++++++++++++ ivi-shell/ivi-layout.c | 2809 +++++++++++++++++++++++++++++++++++++ 6 files changed, 4957 insertions(+) create mode 100644 ivi-shell/ivi-layout-export.h create mode 100644 ivi-shell/ivi-layout-private.h create mode 100644 ivi-shell/ivi-layout-transition.c create mode 100644 ivi-shell/ivi-layout.c diff --git a/Makefile.am b/Makefile.am index 2330933..812b4bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -720,6 +720,26 @@ nodist_fullscreen_shell_la_SOURCES = \ BUILT_SOURCES += $(nodist_fullscreen_shell_la_SOURCES) endif +if ENABLE_IVI_SHELL + +module_LTLIBRARIES += \ + $(ivi_layout) + +ivi_layout = ivi-layout.la +ivi_layout_la_LDFLAGS = -module -avoid-version +ivi_layout_la_LIBADD = $(COMPOSITOR_LIBS) libshared.la +ivi_layout_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) +ivi_layout_la_SOURCES = \ + ivi-shell/ivi-layout-export.h \ + ivi-shell/ivi-layout-private.h \ + ivi-shell/ivi-layout.c \ + ivi-shell/ivi-layout-transition.c + +BUILT_SOURCES += $(nodist_ivi_layout_la_SOURCES) + +endif + + if ENABLE_SCREEN_SHARING module_LTLIBRARIES += screen-share.la diff --git a/configure.ac b/configure.ac index 05e883d..e45dbeb 100644 --- a/configure.ac +++ b/configure.ac @@ -434,6 +434,13 @@ 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") + 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 @@ -523,6 +530,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-export.h b/ivi-shell/ivi-layout-export.h new file mode 100644 index 0000000..18b1dc3 --- /dev/null +++ b/ivi-shell/ivi-layout-export.h @@ -0,0 +1,689 @@ +/* + * 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. + * + * This API and ABI follow following specifications. + * http://projects.genivi.org/wayland-ivi-extension/layer-manager-apis + */ + +#ifndef _IVI_LAYOUT_EXPORT_H_ +#define _IVI_LAYOUT_EXPORT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "stdbool.h" +#include "compositor.h" + +#define IVI_SUCCEEDED (0) +#define IVI_FAILED (-1) + +struct ivi_layout_layer; +struct ivi_layout_screen; +struct ivi_layout_surface; + +struct ivi_layout_surface_properties +{ + wl_fixed_t opacity; + int32_t source_x; + int32_t source_y; + int32_t source_width; + int32_t source_height; + int32_t start_x; + int32_t start_y; + int32_t start_width; + int32_t start_height; + int32_t dest_x; + int32_t dest_y; + int32_t dest_width; + int32_t dest_height; + enum wl_output_transform orientation; + bool visibility; + int32_t transition_type; + uint32_t transition_duration; +}; + +struct ivi_layout_layer_properties +{ + wl_fixed_t opacity; + int32_t source_x; + int32_t source_y; + int32_t source_width; + int32_t source_height; + int32_t dest_x; + int32_t dest_y; + int32_t dest_width; + int32_t dest_height; + enum wl_output_transform orientation; + uint32_t visibility; + int32_t transition_type; + uint32_t transition_duration; + double start_alpha; + double end_alpha; + uint32_t is_fade_in; +}; + +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_CONFIGURE = (1 << 11), + IVI_NOTIFICATION_ALL = 0xFFFF +}; + +enum ivi_layout_transition_type{ + IVI_LAYOUT_TRANSITION_NONE, + IVI_LAYOUT_TRANSITION_VIEW_DEFAULT, + IVI_LAYOUT_TRANSITION_VIEW_DEST_RECT_ONLY, + IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY, + IVI_LAYOUT_TRANSITION_LAYER_FADE, + IVI_LAYOUT_TRANSITION_LAYER_MOVE, + IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER, + IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE, + IVI_LAYOUT_TRANSITION_VIEW_RESIZE, + IVI_LAYOUT_TRANSITION_VIEW_FADE, + IVI_LAYOUT_TRANSITION_MAX, +}; + +typedef void (*layer_property_notification_func)( + struct ivi_layout_layer *ivilayer, + const struct ivi_layout_layer_properties *, + enum ivi_layout_notification_mask mask, + void *userdata); + +typedef void (*surface_property_notification_func)( + struct ivi_layout_surface *ivisurf, + const struct ivi_layout_surface_properties *, + enum ivi_layout_notification_mask mask, + void *userdata); + +typedef void (*layer_create_notification_func)( + struct ivi_layout_layer *ivilayer, + void *userdata); + +typedef void (*layer_remove_notification_func)( + struct ivi_layout_layer *ivilayer, + void *userdata); + +typedef void (*surface_create_notification_func)( + struct ivi_layout_surface *ivisurf, + void *userdata); + +typedef void (*surface_remove_notification_func)( + struct ivi_layout_surface *ivisurf, + void *userdata); + +typedef void (*surface_configure_notification_func)( + struct ivi_layout_surface *ivisurf, + void *userdata); + +typedef void (*ivi_controller_surface_content_callback)( + struct ivi_layout_surface *ivisurf, + int32_t content, + void *userdata); + +/** + * \brief register for notification when layer is created + */ +int32_t +ivi_layout_add_notification_create_layer( + layer_create_notification_func callback, + void *userdata); + +void +ivi_layout_remove_notification_create_layer( + layer_create_notification_func callback, + void *userdata); + +/** + * \brief register for notification when layer is removed + */ +int32_t +ivi_layout_add_notification_remove_layer( + layer_remove_notification_func callback, + void *userdata); + +void +ivi_layout_remove_notification_remove_layer( + layer_remove_notification_func callback, + void *userdata); + +/** + * \brief register for notification when surface is created + */ +int32_t +ivi_layout_add_notification_create_surface( + surface_create_notification_func callback, + void *userdata); + +void +ivi_layout_remove_notification_create_surface( + surface_create_notification_func callback, + void *userdata); + +/** + * \brief register for notification when surface is removed + */ +int32_t +ivi_layout_add_notification_remove_surface( + surface_remove_notification_func callback, + void *userdata); + +void +ivi_layout_remove_notification_remove_surface( + surface_remove_notification_func callback, + void *userdata); + +/** + * \brief register for notification when surface is configured + */ +int32_t +ivi_layout_add_notification_configure_surface( + surface_configure_notification_func callback, + void *userdata); + +void +ivi_layout_remove_notification_configure_surface( + surface_configure_notification_func callback, + void *userdata); + +/** + * \brief get id of surface from ivi_layout_surface + * + * \return id of surface + */ +uint32_t +ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf); + +/** + * \brief get id of layer from ivi_layout_layer + * + * + * \return id of layer + */ +uint32_t +ivi_layout_get_id_of_layer(struct ivi_layout_layer *ivilayer); + +/** + * \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_get_surface_from_id(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_get_screen_from_id(uint32_t id_screen); + +/** + * \brief Get the screen resolution of a specific screen + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_get_screen_resolution(struct ivi_layout_screen *iviscrn, + int32_t *pWidth, + int32_t *pHeight); + +/** + * \brief Set an observer callback for surface content status change. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_set_content_observer( + struct ivi_layout_surface *ivisurf, + ivi_controller_surface_content_callback callback, + void* userdata); + +/** + * \brief Get the layer properties + * + * \return (const struct ivi_layout_layer_properties *) + * if the method call was successful + * \return NULL if the method call was failed + */ +const struct ivi_layout_layer_properties * +ivi_layout_get_properties_of_layer(struct ivi_layout_layer *ivilayer); + +/** + * \brief Get the screens + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_get_screens(int32_t *pLength, struct ivi_layout_screen ***ppArray); + +/** + * \brief Get the screens under the given layer + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_get_screens_under_layer(struct ivi_layout_layer *ivilayer, + int32_t *pLength, + struct ivi_layout_screen ***ppArray); + +/** + * \brief Get all Layers which are currently registered and managed + * by the services + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_get_layers(int32_t *pLength, struct ivi_layout_layer ***ppArray); + +/** + * \brief Get all Layers under the given surface + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_get_layers_under_surface(struct ivi_layout_surface *ivisurf, + int32_t *pLength, + struct ivi_layout_layer ***ppArray); + +/** + * \brief Get all Surfaces which are currently registered and managed + * by the services + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_get_surfaces(int32_t *pLength, struct ivi_layout_surface ***ppArray); + +/** + * \brief Create a layer which should be managed by the service + * + * \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_layer_create_with_dimension(uint32_t id_layer, + int32_t width, int32_t height); + +/** + * \brief Removes a layer which is currently managed by the service + */ +void +ivi_layout_layer_remove(struct ivi_layout_layer *ivilayer); + +/** + * \brief Set the visibility of a layer. If a layer is not visible, the + * layer and its surfaces will not be rendered. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_set_visibility(struct ivi_layout_layer *ivilayer, + bool newVisibility); + +/** + * \brief Set the opacity of a layer. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_set_opacity(struct ivi_layout_layer *ivilayer, + wl_fixed_t opacity); + +/** + * \brief Get the opacity of a layer. + * + * \return opacity if the method call was successful + * \return wl_fixed_from_double(0.0) if the method call was failed + */ +wl_fixed_t +ivi_layout_layer_get_opacity(struct ivi_layout_layer *ivilayer); + +/** + * \brief Set the area of a layer which should be used for the rendering. + * + * Only this part will be visible. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_set_source_rectangle(struct ivi_layout_layer *ivilayer, + int32_t x, int32_t y, + int32_t width, int32_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 IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_set_destination_rectangle(struct ivi_layout_layer *ivilayer, + int32_t x, int32_t y, + int32_t width, int32_t height); + +/** + * \brief Get the horizontal and vertical position of the layer. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_get_position(struct ivi_layout_layer *ivilayer, + int32_t *dest_x, int32_t *dest_y); + +/** + * \brief Sets the horizontal and vertical position of the layer. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_set_position(struct ivi_layout_layer *ivilayer, + int32_t dest_x, int32_t dest_y); + +/** + * \brief Sets the orientation of a layer. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_set_orientation(struct ivi_layout_layer *ivilayer, + enum wl_output_transform orientation); + +/** + * \brief Sets render order of surfaces within one layer + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_set_render_order(struct ivi_layout_layer *ivilayer, + struct ivi_layout_surface **pSurface, + int32_t number); + +/** + * \brief Set the visibility of a surface. + * + * If a surface is not visible it will not be rendered. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_set_visibility(struct ivi_layout_surface *ivisurf, + bool newVisibility); + +/** + * \brief Get the visibility of a surface. + * + * If a surface is not visible it will not be rendered. + * + * \return true if surface is visible + * \return false if surface is invisible or the method call was failed + */ +bool +ivi_layout_surface_get_visibility(struct ivi_layout_surface *ivisurf); + +/** + * \brief Set the opacity of a surface. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_set_opacity(struct ivi_layout_surface *ivisurf, + wl_fixed_t opacity); + +/** + * \brief Get the opacity of a surface. + * + * \return opacity if the method call was successful + * \return wl_fixed_from_double(0.0) if the method call was failed + */ +wl_fixed_t +ivi_layout_surface_get_opacity(struct ivi_layout_surface *ivisurf); + +/** + * \brief Set the destination area of a surface within a layer for rendering. + * + * The surface will be scaled to this rectangle for rendering. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_set_destination_rectangle(struct ivi_layout_surface *ivisurf, + int32_t x, int32_t y, + int32_t width, int32_t height); + +/** + * \brief Sets the orientation of a surface. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_set_orientation(struct ivi_layout_surface *ivisurf, + enum wl_output_transform orientation); + +/** + * \brief Add a layer to a screen which is currently managed by the service + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_screen_add_layer(struct ivi_layout_screen *iviscrn, + struct ivi_layout_layer *addlayer); + +/** + * \brief Sets render order of layers on a display + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_screen_set_render_order(struct ivi_layout_screen *iviscrn, + struct ivi_layout_layer **pLayer, + const int32_t number); + +/** + * \brief register for notification on property changes of layer + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_add_notification(struct ivi_layout_layer *ivilayer, + layer_property_notification_func callback, + void *userdata); + +/** + * \brief remove notification on property changes of layer + */ +void +ivi_layout_layer_remove_notification(struct ivi_layout_layer *ivilayer); + +/** + * \brief register for notification on property changes of surface + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_add_notification(struct ivi_layout_surface *ivisurf, + surface_property_notification_func callback, + void *userdata); + +/** + * \brief remove notification on property changes of surface + */ +void +ivi_layout_surface_remove_notification(struct ivi_layout_surface *ivisurf); + +/** + * \brief Get the surface properties + * + * \return (const struct ivi_surface_layer_properties *) + * if the method call was successful + * \return NULL if the method call was failed + */ +const struct ivi_layout_surface_properties * +ivi_layout_get_properties_of_surface(struct ivi_layout_surface *ivisurf); + +/** + * \brief Add a surface to a layer which is currently managed by the service + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_add_surface(struct ivi_layout_layer *ivilayer, + struct ivi_layout_surface *addsurf); + +/** + * \brief Removes a surface from a layer which is currently managed by the service + */ +void +ivi_layout_layer_remove_surface(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 IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_set_source_rectangle(struct ivi_layout_surface *ivisurf, + int32_t x, int32_t y, + int32_t width, int32_t height); + +/** + * \brief get weston_output from ivi_layout_screen. + * + * \return (struct weston_output *) + * if the method call was successful + * \return NULL if the method call was failed + */ +struct weston_output * +ivi_layout_screen_get_output(struct ivi_layout_screen *); + +struct weston_surface * +ivi_layout_surface_get_weston_surface(struct ivi_layout_surface *ivisurf); + +int32_t +ivi_layout_surface_get_size(struct ivi_layout_surface *ivisurf, + int32_t *width, + int32_t *height, + int32_t *stride); + +int32_t +ivi_layout_layer_set_transition(struct ivi_layout_layer *ivilayer, + enum ivi_layout_transition_type type, + uint32_t duration); + +int32_t +ivi_layout_layer_set_fade_info(struct ivi_layout_layer* layer, + uint32_t is_fade_in, + double start_alpha, double end_alpha); + +int32_t +ivi_layout_surface_set_transition(struct ivi_layout_surface *ivisurf, + enum ivi_layout_transition_type type, + uint32_t duration); + +void +ivi_layout_transition_layer_render_order(struct ivi_layout_layer* layer, + struct ivi_layout_surface** new_order, + uint32_t surface_num, + uint32_t duration); + +void +ivi_layout_transition_move_layer_cancel(struct ivi_layout_layer* layer); + +/** + * \brief Commit all changes and execute all enqueued commands since + * last commit. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_commit_changes(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _IVI_LAYOUT_EXPORT_H_ */ diff --git a/ivi-shell/ivi-layout-private.h b/ivi-shell/ivi-layout-private.h new file mode 100644 index 0000000..8287e93 --- /dev/null +++ b/ivi-shell/ivi-layout-private.h @@ -0,0 +1,319 @@ +/* + * 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. + */ + +#ifndef _ivi_layout_PRIVATE_H_ +#define _ivi_layout_PRIVATE_H_ + +#include "compositor.h" +#include "ivi-layout-export.h" + +struct ivi_layout_surface { + struct wl_list link; + struct wl_signal property_changed; + struct wl_list layer_list; + int32_t update_count; + uint32_t id_surface; + + struct ivi_layout *layout; + struct weston_surface *surface; + + 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_surface_properties prop; + uint32_t event_mask; + + struct { + struct ivi_layout_surface_properties prop; + struct wl_list link; + } pending; + + struct { + struct wl_list link; + struct wl_list layer_list; + } order; + + struct { + ivi_controller_surface_content_callback callback; + void *userdata; + } content_observer; + + struct wl_signal configured; +}; + +struct ivi_layout_layer { + struct wl_list link; + struct wl_signal property_changed; + struct wl_list screen_list; + struct wl_list link_to_surface; + uint32_t id_layer; + + struct ivi_layout *layout; + + struct ivi_layout_layer_properties prop; + uint32_t event_mask; + + struct { + struct ivi_layout_layer_properties prop; + struct wl_list surface_list; + struct wl_list link; + } pending; + + struct { + struct wl_list surface_list; + struct wl_list link; + } order; +}; + +struct ivi_layout { + struct weston_compositor *compositor; + + struct wl_list surface_list; + struct wl_list layer_list; + struct wl_list screen_list; + + struct { + struct wl_signal created; + struct wl_signal removed; + } layer_notification; + + struct { + struct wl_signal created; + struct wl_signal removed; + struct wl_signal configure_changed; + } surface_notification; + + struct weston_layer layout_layer; + struct wl_signal warning_signal; + + struct ivi_layout_transition_set *transitions; + struct wl_list pending_transition_list; +}; + +struct ivi_layout *get_instance(void); + +struct ivi_layout_transition; + +struct ivi_layout_transition_set { + struct wl_event_source *event_source; + struct wl_list transition_list; +}; + +typedef void (*ivi_layout_transition_destroy_user_func)(void *user_data); + +struct ivi_layout_transition_set * +ivi_layout_transition_set_create(struct weston_compositor *ec); + +void +ivi_layout_transition_move_resize_view(struct ivi_layout_surface *surface, + int32_t dest_x, int32_t dest_y, + int32_t dest_width, int32_t dest_height, + uint32_t duration); + +void +ivi_layout_transition_visibility_on(struct ivi_layout_surface *surface, + uint32_t duration); + +void +ivi_layout_transition_visibility_off(struct ivi_layout_surface *surface, + uint32_t duration); + + +void +ivi_layout_transition_move_layer(struct ivi_layout_layer *layer, + int32_t dest_x, int32_t dest_y, + uint32_t duration); + +void +ivi_layout_transition_fade_layer(struct ivi_layout_layer *layer, + uint32_t is_fade_in, + double start_alpha, double end_alpha, + void *user_data, + ivi_layout_transition_destroy_user_func destroy_func, + uint32_t duration); + +int32_t +is_surface_transition(struct ivi_layout_surface *surface); + +/** + * \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_get_layer_from_id(uint32_t id_layer); + +/** + * \brief Remove a surface + */ +void +ivi_layout_surface_remove(struct ivi_layout_surface *ivisurf); + +/** + * \brief Get all Layers of the given screen + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_get_layers_on_screen(struct ivi_layout_screen *iviscrn, + int32_t *pLength, + struct ivi_layout_layer ***ppArray); + +/** + * \brief Get all Surfaces which are currently registered to a given + * layer and are managed by the services + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_get_surfaces_on_layer(struct ivi_layout_layer *ivilayer, + int32_t *pLength, + struct ivi_layout_surface ***ppArray); + +/** + * \brief Get the visibility of a layer. If a layer is not visible, + * the layer and its surfaces will not be rendered. + * + * \return true if layer is visible + * \return false if layer is invisible or the method call was failed + */ +bool +ivi_layout_layer_get_visibility(struct ivi_layout_layer *ivilayer); + +/** + * \brief Get the horizontal and vertical dimension of the layer. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_get_dimension(struct ivi_layout_layer *ivilayer, + int32_t *dest_width, int32_t *dest_height); + +/** + * \brief Set the horizontal and vertical dimension of the layer. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_layer_set_dimension(struct ivi_layout_layer *ivilayer, + int32_t dest_width, int32_t dest_height); + +/** + * \brief Gets the orientation of a layer. + * + * \return (enum wl_output_transform) + * if the method call was successful + * \return WL_OUTPUT_TRANSFORM_NORMAL if the method call was failed + */ +enum wl_output_transform +ivi_layout_layer_get_orientation(struct ivi_layout_layer *ivilayer); + +/** + * \brief Set the horizontal and vertical dimension of the surface. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_set_dimension(struct ivi_layout_surface *ivisurf, + int32_t dest_width, int32_t dest_height); + +/** + * \brief Get the horizontal and vertical dimension of the surface. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_get_dimension(struct ivi_layout_surface *ivisurf, + int32_t *dest_width, int32_t *dest_height); + +/** + * \brief Sets the horizontal and vertical position of the surface. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_set_position(struct ivi_layout_surface *ivisurf, + int32_t dest_x, int32_t dest_y); + +/** + * \brief Get the horizontal and vertical position of the surface. + * + * \return IVI_SUCCEEDED if the method call was successful + * \return IVI_FAILED if the method call was failed + */ +int32_t +ivi_layout_surface_get_position(struct ivi_layout_surface *ivisurf, + int32_t *dest_x, int32_t *dest_y); + +/** + * \brief Gets the orientation of a surface. + * + * \return (enum wl_output_transform) + * if the method call was successful + * \return WL_OUTPUT_TRANSFORM_NORMAL if the method call was failed + */ +enum wl_output_transform +ivi_layout_surface_get_orientation(struct ivi_layout_surface *ivisurf); + +int32_t +ivi_layout_surface_set_transition_duration( + struct ivi_layout_surface *ivisurf, + uint32_t duration); + +struct ivi_layout_interface { + struct weston_view *(*get_weston_view)( + struct ivi_layout_surface *surface); + + void (*surface_configure)(struct ivi_layout_surface *ivisurf, + int32_t width, + int32_t height); + + struct ivi_layout_surface *(*surface_create)( + struct weston_surface *wl_surface, + uint32_t id_surface); + + void (*init_with_compositor)(struct weston_compositor *ec); + + int32_t (*get_surface_dimension)( + struct ivi_layout_surface *ivisurf, + int32_t *dest_width, + int32_t *dest_height); + + void (*add_surface_configured_listener)( + struct ivi_layout_surface *ivisurf, + struct wl_listener* listener); +}; + +#endif diff --git a/ivi-shell/ivi-layout-transition.c b/ivi-shell/ivi-layout-transition.c new file mode 100644 index 0000000..0c45c4a --- /dev/null +++ b/ivi-shell/ivi-layout-transition.c @@ -0,0 +1,1111 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "ivi-layout-export.h" +#include "ivi-layout-private.h" + +struct ivi_layout_transition; + +typedef void (*ivi_layout_transition_frame_func)( + struct ivi_layout_transition *transition); +typedef void (*ivi_layout_transition_destroy_func)( + struct ivi_layout_transition *transition); +typedef int32_t (*ivi_layout_is_transition_func)(void *private_data, void *id); + +struct ivi_layout_transition { + enum ivi_layout_transition_type type; + void *private_data; + void *user_data; + + uint32_t time_start; + uint32_t time_duration; + uint32_t time_elapsed; + uint32_t is_done; + ivi_layout_is_transition_func is_transition_func; + ivi_layout_transition_frame_func frame_func; + ivi_layout_transition_destroy_func destroy_func; +}; + +struct transition_node { + struct ivi_layout_transition *transition; + struct wl_list link; +}; + +static void layout_transition_destroy(struct ivi_layout_transition *transition); + +static struct ivi_layout_transition * +get_transition_from_type_and_id(enum ivi_layout_transition_type type, + void *id_data) +{ + struct ivi_layout *layout = get_instance(); + struct transition_node *node; + struct ivi_layout_transition *tran; + + wl_list_for_each(node, &layout->transitions->transition_list, link) { + tran = node->transition; + + if (tran->type == type && + tran->is_transition_func(tran->private_data, id_data)) + return tran; + } + + return NULL; +} + +WL_EXPORT int32_t +is_surface_transition(struct ivi_layout_surface *surface) +{ + struct ivi_layout *layout = get_instance(); + struct transition_node *node; + struct ivi_layout_transition *tran; + + wl_list_for_each(node, &layout->transitions->transition_list, link) { + tran = node->transition; + + if ((tran->type == IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE || + tran->type == IVI_LAYOUT_TRANSITION_VIEW_RESIZE) && + tran->is_transition_func(tran->private_data, surface)) + return 1; + } + + return 0; +} + +static void +tick_transition(struct ivi_layout_transition *transition, uint32_t timestamp) +{ + const double t = timestamp - transition->time_start; + + if (transition->time_duration <= t) { + transition->time_elapsed = transition->time_duration; + transition->is_done = 1; + } else { + transition->time_elapsed = t; + } +} + +static float time_to_nowpos(struct ivi_layout_transition *transition) +{ + return sin((float)transition->time_elapsed / + (float)transition->time_duration * M_PI_2); +} + +static void +do_transition_frame(struct ivi_layout_transition *transition, + uint32_t timestamp) +{ + if (0 == transition->time_start) + transition->time_start = timestamp; + + tick_transition(transition, timestamp); + transition->frame_func(transition); + + if (transition->is_done) + layout_transition_destroy(transition); +} + +static int32_t +layout_transition_frame(void *data) +{ + struct ivi_layout_transition_set *transitions = data; + uint32_t fps = 30; + struct timespec timestamp = {}; + uint32_t msec = 0; + struct transition_node *node = NULL; + struct transition_node *next = NULL; + + if (wl_list_empty(&transitions->transition_list)) { + wl_event_source_timer_update(transitions->event_source, 0); + return 1; + } + + wl_event_source_timer_update(transitions->event_source, 1000 / fps); + + clock_gettime(CLOCK_MONOTONIC, ×tamp);//FIXME; + msec = (1e+3 * timestamp.tv_sec + 1e-6 * timestamp.tv_nsec); + + wl_list_for_each_safe(node, next, &transitions->transition_list, link) { + do_transition_frame(node->transition, msec); + } + + ivi_layout_commit_changes(); + return 1; +} + +WL_EXPORT struct ivi_layout_transition_set * +ivi_layout_transition_set_create(struct weston_compositor *ec) +{ + struct ivi_layout_transition_set *transitions; + struct wl_event_loop *loop; + + transitions = malloc(sizeof(*transitions)); + if (transitions == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return NULL; + } + + wl_list_init(&transitions->transition_list); + + loop = wl_display_get_event_loop(ec->wl_display); + transitions->event_source = + wl_event_loop_add_timer(loop, layout_transition_frame, + transitions); + + return transitions; +} + +static void +layout_transition_register(struct ivi_layout_transition *trans) +{ + struct ivi_layout *layout = get_instance(); + struct transition_node *node; + + node = malloc(sizeof(*node)); + if (node == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return; + } + + node->transition = trans; + wl_list_insert(&layout->pending_transition_list, &node->link); +} + +static void +remove_transition(struct ivi_layout *layout, + struct ivi_layout_transition *trans) +{ + struct transition_node *node; + struct transition_node *next; + + wl_list_for_each_safe(node, next, + &layout->transitions->transition_list, link) { + if (node->transition == trans) { + wl_list_remove(&node->link); + free(node); + return; + } + } + + wl_list_for_each_safe(node, next, + &layout->pending_transition_list, link) { + if (node->transition == trans) { + wl_list_remove(&node->link); + free(node); + return; + } + } +} + +static void +layout_transition_destroy(struct ivi_layout_transition *transition) +{ + struct ivi_layout *layout = get_instance(); + + remove_transition(layout, transition); + if(transition->destroy_func) + transition->destroy_func(transition); + free(transition); +} + +static struct ivi_layout_transition * +create_layout_transition(void) +{ + struct ivi_layout_transition *transition = malloc(sizeof(*transition)); + + if (transition == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return NULL; + } + + transition->type = IVI_LAYOUT_TRANSITION_MAX; + transition->time_start = 0; + transition->time_duration = 300; /* 300ms */ + transition->time_elapsed = 0; + + transition->is_done = 0; + + transition->private_data = NULL; + transition->user_data = NULL; + + transition->frame_func = NULL; + transition->destroy_func = NULL; + + return transition; +} + +/* move and resize view transition */ + +struct move_resize_view_data { + struct ivi_layout_surface *surface; + int32_t start_x; + int32_t start_y; + int32_t end_x; + int32_t end_y; + int32_t start_width; + int32_t start_height; + int32_t end_width; + int32_t end_height; +}; + +static void +transition_move_resize_view_destroy(struct ivi_layout_transition *transition) +{ + struct move_resize_view_data *data = + (struct move_resize_view_data *)transition->private_data; + struct ivi_layout_surface *layout_surface = data->surface; + + wl_signal_emit(&layout_surface->configured, layout_surface); + + if (transition->private_data) { + free(transition->private_data); + transition->private_data = NULL; + } +} + +static void +transition_move_resize_view_user_frame(struct ivi_layout_transition *transition) +{ + struct move_resize_view_data *mrv = transition->private_data; + const double current = time_to_nowpos(transition); + + const int32_t destx = mrv->start_x + + (mrv->end_x - mrv->start_x) * current; + + const int32_t desty = mrv->start_y + + (mrv->end_y - mrv->start_y) * current; + + const int32_t dest_width = mrv->start_width + + (mrv->end_width - mrv->start_width) * current; + + const int32_t dest_height = mrv->start_height + + (mrv->end_height - mrv->start_height) * current; + + ivi_layout_surface_set_destination_rectangle(mrv->surface, + destx, desty, + dest_width, dest_height); +} + +static int32_t +is_transition_move_resize_view_func(struct move_resize_view_data *data, + struct ivi_layout_surface *view) +{ + return data->surface == view; +} + +static struct ivi_layout_transition * +create_move_resize_view_transition( + struct ivi_layout_surface *surface, + int32_t start_x, int32_t start_y, + int32_t end_x, int32_t end_y, + int32_t start_width, int32_t start_height, + int32_t end_width, int32_t end_height, + ivi_layout_transition_frame_func frame_func, + ivi_layout_transition_destroy_func destroy_func, + uint32_t duration) +{ + struct ivi_layout_transition *transition = create_layout_transition(); + struct move_resize_view_data *data = malloc(sizeof(*data)); + + if (data == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return NULL; + } + + transition->type = IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE; + transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_move_resize_view_func; + + transition->frame_func = frame_func; + transition->destroy_func = destroy_func; + transition->private_data = data; + + if (duration != 0) + transition->time_duration = duration; + + data->surface = surface; + data->start_x = start_x; + data->start_y = start_y; + data->end_x = end_x; + data->end_y = end_y; + + data->start_width = start_width; + data->start_height = start_height; + data->end_width = end_width; + data->end_height = end_height; + + return transition; +} + +WL_EXPORT void +ivi_layout_transition_move_resize_view(struct ivi_layout_surface *surface, + int32_t dest_x, int32_t dest_y, + int32_t dest_width, int32_t dest_height, + uint32_t duration) +{ + struct ivi_layout_transition *transition; + int32_t start_pos[2] = { + surface->pending.prop.start_x, + surface->pending.prop.start_y + }; + + int32_t start_size[2] = { + surface->pending.prop.start_width, + surface->pending.prop.start_height + }; + + transition = get_transition_from_type_and_id( + IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE, + surface); + if (transition) { + struct move_resize_view_data *data = transition->private_data; + transition->time_start = 0; + transition->time_duration = duration; + + data->start_x = start_pos[0]; + data->start_y = start_pos[1]; + data->end_x = dest_x; + data->end_y = dest_y; + + data->start_width = start_size[0]; + data->start_height = start_size[1]; + data->end_width = dest_width; + data->end_height = dest_height; + return; + } + + transition = create_move_resize_view_transition( + surface, + start_pos[0], start_pos[1], + dest_x, dest_y, + start_size[0], start_size[1], + dest_width, dest_height, + transition_move_resize_view_user_frame, + transition_move_resize_view_destroy, + duration); + + layout_transition_register(transition); +} + +/* fade transition */ +struct fade_view_data { + struct ivi_layout_surface *surface; + double start_alpha; + double end_alpha; +}; + +struct store_alpha{ + double alpha; +}; + +static void +fade_view_user_frame(struct ivi_layout_transition *transition) +{ + struct fade_view_data *fade = transition->private_data; + struct ivi_layout_surface *surface = fade->surface; + + const double current = time_to_nowpos(transition); + const double alpha = fade->start_alpha + + (fade->end_alpha - fade->start_alpha) * current; + + ivi_layout_surface_set_opacity(surface, wl_fixed_from_double(alpha)); + ivi_layout_surface_set_visibility(surface, true); +} + +static int32_t +is_transition_fade_view_func(struct fade_view_data *data, + struct ivi_layout_surface *view) +{ + return data->surface == view; +} + +static struct ivi_layout_transition * +create_fade_view_transition( + struct ivi_layout_surface *surface, + double start_alpha, double end_alpha, + ivi_layout_transition_frame_func frame_func, + void *user_data, + ivi_layout_transition_destroy_func destroy_func, + uint32_t duration) +{ + struct ivi_layout_transition *transition = create_layout_transition(); + struct fade_view_data *data = malloc(sizeof(*data)); + + if (data == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return NULL; + } + + transition->type = IVI_LAYOUT_TRANSITION_VIEW_FADE; + transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_fade_view_func; + + transition->user_data = user_data; + transition->private_data = data; + transition->frame_func = frame_func; + transition->destroy_func = destroy_func; + + if (duration != 0) + transition->time_duration = duration; + + data->surface = surface; + data->start_alpha = start_alpha; + data->end_alpha = end_alpha; + + return transition; +} + +static void +create_visibility_transition(struct ivi_layout_surface *surface, + double start_alpha, + double dest_alpha, + void *user_data, + ivi_layout_transition_destroy_func destroy_func, + uint32_t duration) +{ + struct ivi_layout_transition *transition = NULL; + + transition = create_fade_view_transition( + surface, + start_alpha, dest_alpha, + fade_view_user_frame, + user_data, + destroy_func, + duration); + + layout_transition_register(transition); +} + +static void +visibility_on_transition_destroy(struct ivi_layout_transition *transition) +{ + struct fade_view_data *data = transition->private_data; + struct store_alpha *user_data = transition->user_data; + + ivi_layout_surface_set_visibility(data->surface, true); + + free(data); + transition->private_data = NULL; + + free(user_data); + transition->user_data = NULL; +} + +WL_EXPORT void +ivi_layout_transition_visibility_on(struct ivi_layout_surface *surface, + uint32_t duration) +{ + struct ivi_layout_transition *transition; + bool is_visible = ivi_layout_surface_get_visibility(surface); + wl_fixed_t dest_alpha = ivi_layout_surface_get_opacity(surface); + struct store_alpha *user_data = NULL; + wl_fixed_t start_alpha = 0.0; + struct fade_view_data *data = NULL; + + transition = get_transition_from_type_and_id( + IVI_LAYOUT_TRANSITION_VIEW_FADE, + surface); + if (transition) { + start_alpha = ivi_layout_surface_get_opacity(surface); + user_data = transition->user_data; + data = transition->private_data; + + transition->time_start = 0; + transition->time_duration = duration; + transition->destroy_func = visibility_on_transition_destroy; + + data->start_alpha = wl_fixed_to_double(start_alpha); + data->end_alpha = user_data->alpha; + return; + } + + if (is_visible) + return; + + user_data = malloc(sizeof(*user_data)); + if (user_data == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return; + } + + user_data->alpha = wl_fixed_to_double(dest_alpha); + + create_visibility_transition(surface, + 0.0, // start_alpha + wl_fixed_to_double(dest_alpha), + user_data, + visibility_on_transition_destroy, + duration); +} + +static void +visibility_off_transition_destroy(struct ivi_layout_transition *transition) +{ + struct fade_view_data *data = transition->private_data; + struct store_alpha *user_data = transition->user_data; + + ivi_layout_surface_set_visibility(data->surface, false); + + ivi_layout_surface_set_opacity(data->surface, + wl_fixed_from_double(user_data->alpha)); + + free(data); + transition->private_data = NULL; + + free(user_data); + transition->user_data= NULL; +} + +WL_EXPORT void +ivi_layout_transition_visibility_off(struct ivi_layout_surface *surface, + uint32_t duration) +{ + struct ivi_layout_transition *transition; + wl_fixed_t start_alpha = ivi_layout_surface_get_opacity(surface); + struct store_alpha* user_data = NULL; + struct fade_view_data* data = NULL; + + transition = + get_transition_from_type_and_id(IVI_LAYOUT_TRANSITION_VIEW_FADE, + surface); + if (transition) { + data = transition->private_data; + + transition->time_start = 0; + transition->time_duration = duration; + transition->destroy_func = visibility_off_transition_destroy; + + data->start_alpha = wl_fixed_to_double(start_alpha); + data->end_alpha = 0; + return; + } + + user_data = malloc(sizeof(*user_data)); + if (user_data == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return; + } + + user_data->alpha = wl_fixed_to_double(start_alpha); + + create_visibility_transition(surface, + wl_fixed_to_double(start_alpha), + 0.0, // dest_alpha + user_data, + visibility_off_transition_destroy, + duration); +} + +/* move layer transition */ + +struct move_layer_data { + struct ivi_layout_layer *layer; + int32_t start_x; + int32_t start_y; + int32_t end_x; + int32_t end_y; + ivi_layout_transition_destroy_user_func destroy_func; +}; + +static void +transition_move_layer_user_frame(struct ivi_layout_transition *transition) +{ + struct move_layer_data *data = transition->private_data; + struct ivi_layout_layer *layer = data->layer; + + const float current = time_to_nowpos(transition); + + const int32_t dest_x = data->start_x + + (data->end_x - data->start_x) * current; + + const int32_t dest_y = data->start_y + + (data->end_y - data->start_y) * current; + + ivi_layout_layer_set_position(layer, dest_x, dest_y); +} + +static void +transition_move_layer_destroy(struct ivi_layout_transition *transition) +{ + struct move_layer_data *data = transition->private_data; + + if(data->destroy_func) + data->destroy_func(transition->user_data); + + free(data); + transition->private_data = NULL; +} + +static int32_t +is_transition_move_layer_func(struct move_layer_data *data, + struct ivi_layout_layer *layer) +{ + return data->layer == layer; +} + + +static struct ivi_layout_transition * +create_move_layer_transition( + struct ivi_layout_layer *layer, + int32_t start_x, int32_t start_y, + int32_t end_x, int32_t end_y, + void *user_data, + ivi_layout_transition_destroy_user_func destroy_user_func, + uint32_t duration) +{ + struct ivi_layout_transition *transition = create_layout_transition(); + struct move_layer_data *data = malloc(sizeof(*data)); + + if (data == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return NULL; + } + + transition->type = IVI_LAYOUT_TRANSITION_LAYER_MOVE; + transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_move_layer_func; + + transition->frame_func = transition_move_layer_user_frame; + transition->destroy_func = transition_move_layer_destroy; + transition->private_data = data; + transition->user_data = user_data; + + if (duration != 0) + transition->time_duration = duration; + + data->layer = layer; + data->start_x = start_x; + data->start_y = start_y; + data->end_x = end_x; + data->end_y = end_y; + data->destroy_func = destroy_user_func; + + return transition; +} + +WL_EXPORT void +ivi_layout_transition_move_layer(struct ivi_layout_layer *layer, + int32_t dest_x, int32_t dest_y, + uint32_t duration) +{ + int32_t start_pos_x = 0; + int32_t start_pos_y = 0; + struct ivi_layout_transition *transition = NULL; + + ivi_layout_layer_get_position(layer, &start_pos_x, &start_pos_y); + + transition = create_move_layer_transition( + layer, + start_pos_x, start_pos_y, + dest_x, dest_y, + NULL, NULL, + duration); + + layout_transition_register(transition); + + return; +} + +WL_EXPORT void +ivi_layout_transition_move_layer_cancel(struct ivi_layout_layer *layer) +{ + struct ivi_layout_transition *transition = + get_transition_from_type_and_id( + IVI_LAYOUT_TRANSITION_LAYER_MOVE, + layer); + if (transition) { + layout_transition_destroy(transition); + } +} + +/* fade layer transition */ +struct fade_layer_data { + struct ivi_layout_layer *layer; + uint32_t is_fade_in; + double start_alpha; + double end_alpha; + ivi_layout_transition_destroy_user_func destroy_func; +}; + +static void +transition_fade_layer_destroy(struct ivi_layout_transition *transition) +{ + struct fade_layer_data *data = transition->private_data; + transition->private_data = NULL; + + free(data); +} + +static void +transition_fade_layer_user_frame(struct ivi_layout_transition *transition) +{ + double current = time_to_nowpos(transition); + struct fade_layer_data *data = transition->private_data; + double alpha = data->start_alpha + + (data->end_alpha - data->start_alpha) * current; + wl_fixed_t fixed_alpha = wl_fixed_from_double(alpha); + + int32_t is_done = transition->is_done; + bool is_visible = !is_done || data->is_fade_in; + + ivi_layout_layer_set_opacity(data->layer, fixed_alpha); + ivi_layout_layer_set_visibility(data->layer, is_visible); +} + +static int32_t +is_transition_fade_layer_func(struct fade_layer_data *data, + struct ivi_layout_layer *layer) +{ + return data->layer == layer; +} + +WL_EXPORT void +ivi_layout_transition_fade_layer( + struct ivi_layout_layer *layer, + uint32_t is_fade_in, + double start_alpha, double end_alpha, + void* user_data, + ivi_layout_transition_destroy_user_func destroy_func, + uint32_t duration) +{ + struct ivi_layout_transition *transition; + struct fade_layer_data *data = NULL; + wl_fixed_t fixed_opacity = 0.0; + double now_opacity = 0.0; + double remain = 0.0; + + transition = get_transition_from_type_and_id( + IVI_LAYOUT_TRANSITION_LAYER_FADE, + layer); + if (transition) { + /* transition update */ + data = transition->private_data; + + /* FIXME */ + fixed_opacity = ivi_layout_layer_get_opacity(layer); + now_opacity = wl_fixed_to_double(fixed_opacity); + remain = 0.0; + + data->is_fade_in = is_fade_in; + data->start_alpha = now_opacity; + data->end_alpha = end_alpha; + + remain = is_fade_in? 1.0 - now_opacity : now_opacity; + transition->time_start = 0; + transition->time_elapsed = 0; + transition->time_duration = duration * remain; + + return; + } + + transition = create_layout_transition(); + data = malloc(sizeof(*data)); + + if (data == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return; + } + + transition->type = IVI_LAYOUT_TRANSITION_LAYER_FADE; + transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_fade_layer_func; + + transition->private_data = data; + transition->user_data = user_data; + + transition->frame_func = transition_fade_layer_user_frame; + transition->destroy_func = transition_fade_layer_destroy; + + if (duration != 0) + transition->time_duration = duration; + + data->layer = layer; + data->is_fade_in = is_fade_in; + data->start_alpha = start_alpha; + data->end_alpha = end_alpha; + data->destroy_func = destroy_func; + + layout_transition_register(transition); + + return; +} + +/* render order transition */ +struct surface_reorder { + uint32_t id_surface; + uint32_t new_index; +}; + +struct change_order_data { + struct ivi_layout_layer *layer; + uint32_t surface_num; + struct surface_reorder *reorder; +}; + +struct surf_with_index { + uint32_t id_surface; + float surface_index; +}; + +static int +cmp_order_asc(const void *lhs, const void *rhs) +{ + const struct surf_with_index *l = lhs; + const struct surf_with_index *r = rhs; + + return l->surface_index > r->surface_index; +} + +/* +render oerder transition + +index 0 1 2 +old surfA, surfB, surfC +new surfB, surfC, surfA + (-1) (-1) (+2) + +after 10% of time elapsed + 0.2 0.9 1.9 + surfA, surfB, surfC + +after 50% of time elapsed + 0.5 1.0 1.5 + surfB, surfA, surfC +*/ + +static void +transition_change_order_user_frame(struct ivi_layout_transition *transition) +{ + uint32_t i, old_index; + double current = time_to_nowpos(transition); + struct change_order_data *data = transition->private_data; + + struct surf_with_index *swi = malloc(sizeof(*swi) * data->surface_num); + struct ivi_layout_surface **new_surface_order = NULL; + uint32_t surface_num = 0; + + if (swi == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return; + } + + for (old_index = 0; old_index < data->surface_num; old_index++) { + swi[old_index].id_surface = data->reorder[old_index].id_surface; + swi[old_index].surface_index = (float)old_index + + ((float)data->reorder[old_index].new_index - (float)old_index) * current; + } + + qsort(swi, data->surface_num, sizeof(*swi), cmp_order_asc); + + new_surface_order = + malloc(sizeof(*new_surface_order) * data->surface_num); + + if (new_surface_order == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return; + } + + for (i = 0; i < data->surface_num; i++) { + struct ivi_layout_surface *surf = + ivi_layout_get_surface_from_id(swi[i].id_surface); + if(surf) + new_surface_order[surface_num++] = surf; + } + + ivi_layout_layer_set_render_order(data->layer, new_surface_order, + surface_num); + + free(new_surface_order); + free(swi); +} + +static void +transition_change_order_destroy(struct ivi_layout_transition *transition) +{ + struct change_order_data *data = transition->private_data; + + free(data->reorder); + free(data); +} + +static int32_t find_surface(struct ivi_layout_surface **surfaces, + uint32_t surface_num, + struct ivi_layout_surface *target) +{ + uint32_t i = 0; + + for(i = 0; i < surface_num; i++) { + if (surfaces[i] == target) + return i; + } + + return -1; +} + +static int32_t +is_transition_change_order_func(struct change_order_data *data, + struct ivi_layout_layer *layer) +{ + return data->layer == layer; +} + +WL_EXPORT void +ivi_layout_transition_layer_render_order(struct ivi_layout_layer *layer, + struct ivi_layout_surface **new_order, + uint32_t surface_num, + uint32_t duration) +{ + struct surface_reorder *reorder; + struct ivi_layout_surface *surf; + uint32_t old_index = 0; + struct ivi_layout_transition *transition; + struct change_order_data *data = NULL; + int32_t new_index = 0; + uint32_t id = 0; + + reorder = malloc(sizeof(*reorder) * surface_num); + if (reorder == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return; + } + + wl_list_for_each(surf, &layer->order.surface_list, order.link) { + new_index = find_surface(new_order, surface_num, surf); + id = ivi_layout_get_id_of_surface(surf); + if(new_index < 0){ + fprintf(stderr, "invalid render order!!!\n"); + return; + } + + reorder[old_index].id_surface = id; + reorder[old_index].new_index = new_index; + old_index++; + } + + transition = get_transition_from_type_and_id( + IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER, + layer); + if (transition) { + /* update transition */ + struct change_order_data *data = transition->private_data; + transition->time_start = 0; /* timer reset */ + + if (duration != 0) { + transition->time_duration = duration; + } + + free(data->reorder); + data->reorder = reorder; + return; + } + + transition = create_layout_transition(); + data = malloc(sizeof(*data)); + + if (data == NULL) { + weston_log("%s: memory allocation fails\n", __func__); + return; + } + + transition->type = IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER; + transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_change_order_func; + + transition->private_data = data; + transition->frame_func = transition_change_order_user_frame; + transition->destroy_func = transition_change_order_destroy; + + if (duration != 0) + transition->time_duration = duration; + + data->layer = layer; + data->reorder = reorder; + data->surface_num = old_index; + + layout_transition_register(transition); +} + +WL_EXPORT int32_t +ivi_layout_surface_set_transition(struct ivi_layout_surface *ivisurf, + enum ivi_layout_transition_type type, + uint32_t duration) +{ + struct ivi_layout_surface_properties *prop; + + if (ivisurf == NULL) { + weston_log("%s: invalid argument\n", __func__); + return -1; + } + + prop = &ivisurf->pending.prop; + prop->transition_type = type; + prop->transition_duration = duration; + return 0; +} + +int32_t +ivi_layout_surface_set_transition_duration(struct ivi_layout_surface *ivisurf, + uint32_t duration) +{ + struct ivi_layout_surface_properties *prop; + + if (ivisurf == NULL) { + weston_log("%s: invalid argument\n", __func__); + return -1; + } + + prop = &ivisurf->pending.prop; + prop->transition_duration = duration*10; + return 0; +} + +WL_EXPORT int32_t +ivi_layout_layer_set_transition(struct ivi_layout_layer *ivilayer, + enum ivi_layout_transition_type type, + uint32_t duration) +{ + if (ivilayer == NULL) { + weston_log("%s: invalid argument\n", __func__); + return -1; + } + + ivilayer->pending.prop.transition_type = type; + ivilayer->pending.prop.transition_duration = duration; + + return 0; +} + +WL_EXPORT int32_t +ivi_layout_layer_set_fade_info(struct ivi_layout_layer* ivilayer, + uint32_t is_fade_in, + double start_alpha, double end_alpha) +{ + if (ivilayer == NULL) { + weston_log("%s: invalid argument\n", __func__); + return -1; + } + + ivilayer->pending.prop.is_fade_in = is_fade_in; + ivilayer->pending.prop.start_alpha = start_alpha; + ivilayer->pending.prop.end_alpha = end_alpha; + + return 0; +} diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c new file mode 100644 index 0000000..6f7c3c2 --- /dev/null +++ b/ivi-shell/ivi-layout.c @@ -0,0 +1,2809 @@ +/* + * 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 ivi_screen is + * not updated till calling ivi_layout_commit_changes. A overview from + * calling API for updating properties of ivi_surface/ivi_layer to asking + * compositor to compose them by using weston_compositor_schedule_repaint, + * 0/ initialize this library by ivi_layout_init_with_compositor + * with (struct weston_compositor *ec) from ivi-shell. + * 1/ When a API for updating properties of ivi_surface/ivi_layer, it updates + * pending prop of ivi_surface/ivi_layer/ivi_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. + * + * *) ivi_layout_commitChanges is also called by transition animation + * per each frame. See ivi-layout-transition.c in details. Transition + * animation interpolates frames between previous properties of ivi_surface + * and new ones. + * For example, when a property of ivi_surface is changed from invisibility + * to visibility, it behaves like fade-in. When ivi_layout_commitChange is + * called during transition animation, it cancels the transition and + * re-start transition to new properties from current properties of final + * frame just before the the cancellation. + * + * 4/ According properties, set transformation by using weston_matrix and + * weston_view per ivi_surfaces and ivi_layers in while loop. + * 5/ Set damage and trigger transform by using weston_view_geometry_dirty. + * 6/ Notify update of properties. + * 7/ Trigger composition by weston_compositor_schedule_repaint. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "compositor.h" +#include "ivi-layout-export.h" +#include "ivi-layout-private.h" + +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 listener_layout_notification { + void *userdata; + struct wl_listener listener; +}; + +struct ivi_layout; + +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 layer_list; + struct wl_list link; + } pending; + + struct { + struct wl_list layer_list; + struct wl_list link; + } order; +}; + +struct ivi_layout_notification_callback { + void *callback; + void *data; +}; + +static struct ivi_layout ivilayout = {0}; + +struct ivi_layout * +get_instance(void) +{ + return &ivilayout; +} + +/** + * Internal API to add/remove a link to ivi_surface from ivi_layer. + */ +static void +add_link_to_surface(struct ivi_layout_layer *ivilayer, + struct link_layer *link_layer) +{ + struct link_layer *link = NULL; + + wl_list_for_each(link, &ivilayer->link_to_surface, link_to_layer) { + if (link == link_layer) + return; + } + + 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); + } + if (!wl_list_empty(&link->link)) { + wl_list_remove(&link->link); + } + free(link); + } + + wl_list_init(&ivilayer->link_to_surface); +} + +/** + * Internal API to add a link to ivi_layer from ivi_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 ivi_surface from ivi_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->layer_list, &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->layer_list, link) { + if (!wl_list_empty(&link_layer->link)) { + wl_list_remove(&link_layer->link); + } + if (!wl_list_empty(&link_layer->link_to_layer)) { + wl_list_remove(&link_layer->link_to_layer); + } + free(link_layer); + } + wl_list_init(&ivisurf->layer_list); +} + +/** + * Internal API to add/remove a ivi_layer to/from ivi_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->screen_list, &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->screen_list, link) { + if (!wl_list_empty(&link_scrn->link)) { + wl_list_remove(&link_scrn->link); + } + if (!wl_list_empty(&link_scrn->link_to_screen)) { + wl_list_remove(&link_scrn->link_to_screen); + } + free(link_scrn); + } + wl_list_init(&ivilayer->screen_list); +} + +/** + * Internal API to add/remove a ivi_layer to/from ivi_screen. + */ +static struct ivi_layout_surface * +get_surface(struct wl_list *surf_list, uint32_t id_surface) +{ + struct ivi_layout_surface *ivisurf; + + wl_list_for_each(ivisurf, surf_list, link) { + if (ivisurf->id_surface == id_surface) { + return ivisurf; + } + } + + return NULL; +} + +static struct ivi_layout_layer * +get_layer(struct wl_list *layer_list, uint32_t id_layer) +{ + struct ivi_layout_layer *ivilayer; + + wl_list_for_each(ivilayer, layer_list, 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); + + 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); + + ivisurf->surface = NULL; + ivi_layout_surface_remove(ivisurf); +} + +/** + * Internal API to check ivi_layer/ivi_surface already added in ivi_layer/ivi_screen. + * Called by ivi_layout_layer_add_surface/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.surface_list, 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.layer_list, pending.link) { + if (layer->id_layer == ivilayer->id_layer) { + return 1; + } + } + + return 0; +} + +/** + * Internal API to initialize ivi_screens found from output_list of weston_compositor. + * Called by ivi_layout_init_with_compositor. + */ +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.layer_list); + wl_list_init(&iviscrn->pending.link); + + wl_list_init(&iviscrn->order.layer_list); + wl_list_init(&iviscrn->order.link); + + wl_list_init(&iviscrn->link_to_layer); + + wl_list_insert(&layout->screen_list, &iviscrn->link); + } +} + +/** + * Internal APIs to initialize properties of ivi_surface/ivi_layer when they are created. + */ +static void +init_layer_properties(struct ivi_layout_layer_properties *prop, + int32_t width, int32_t height) +{ + memset(prop, 0, sizeof *prop); + prop->opacity = wl_fixed_from_double(1.0); + prop->source_width = width; + prop->source_height = height; + prop->dest_width = width; + prop->dest_height = height; +} + +static void +init_surface_properties(struct ivi_layout_surface_properties *prop) +{ + memset(prop, 0, sizeof *prop); + prop->opacity = wl_fixed_from_double(1.0); +} + +/** + * Internal APIs to be called from ivi_layout_commit_changes. + */ +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)) { + struct weston_view *tmpview = NULL; + wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) { + if (tmpview == NULL) { + continue; + } + tmpview->alpha = layer_alpha * surf_alpha; + } + } +} + +static void +update_surface_orientation(struct ivi_layout_layer *ivilayer, + struct ivi_layout_surface *ivisurf) +{ + struct weston_view *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; + + wl_list_for_each(view, &ivisurf->surface->views, surface_link) { + if (view != NULL) { + break; + } + } + + if (view == NULL) { + return; + } + + if ((ivilayer->prop.dest_width == 0) || + (ivilayer->prop.dest_height == 0)) { + return; + } + width = (float)ivilayer->prop.dest_width; + height = (float)ivilayer->prop.dest_height; + + switch (ivisurf->prop.orientation) { + case WL_OUTPUT_TRANSFORM_NORMAL: + v_sin = 0.0f; + v_cos = 1.0f; + break; + case WL_OUTPUT_TRANSFORM_90: + v_sin = 1.0f; + v_cos = 0.0f; + sx = width / height; + sy = height / width; + break; + case WL_OUTPUT_TRANSFORM_180: + v_sin = 0.0f; + v_cos = -1.0f; + break; + case WL_OUTPUT_TRANSFORM_270: + 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; + 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; + + wl_list_for_each(view, &ivisurf->surface->views, surface_link) { + if (view != NULL) { + break; + } + } + + 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 WL_OUTPUT_TRANSFORM_NORMAL: + v_sin = 0.0f; + v_cos = 1.0f; + break; + case WL_OUTPUT_TRANSFORM_90: + v_sin = 1.0f; + v_cos = 0.0f; + sx = width / height; + sy = height / width; + break; + case WL_OUTPUT_TRANSFORM_180: + v_sin = 0.0f; + v_cos = -1.0f; + break; + case WL_OUTPUT_TRANSFORM_270: + 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; + float tx = (float)ivisurf->prop.dest_x; + float ty = (float)ivisurf->prop.dest_y; + struct weston_matrix *matrix = &ivisurf->surface_pos.matrix; + + wl_list_for_each(view, &ivisurf->surface->views, surface_link) { + if (view != NULL) { + break; + } + } + + 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); +} + +static void +update_layer_position(struct ivi_layout_layer *ivilayer, + struct ivi_layout_surface *ivisurf) +{ + struct weston_view *view; + struct weston_matrix *matrix = &ivisurf->layer_pos.matrix; + float tx = (float)ivilayer->prop.dest_x; + float ty = (float)ivilayer->prop.dest_y; + + wl_list_for_each(view, &ivisurf->surface->views, surface_link) { + if (view != NULL) { + break; + } + } + + 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; + 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; + + wl_list_for_each(view, &ivisurf->surface->views, surface_link) { + if (view != NULL) { + break; + } + } + + if (view == NULL) { + return; + } + + if (ivisurf->prop.dest_width == 0 && ivisurf->prop.dest_height == 0) { + ivisurf->prop.dest_width = ivisurf->surface->width_from_buffer; + ivisurf->prop.dest_height = ivisurf->surface->height_from_buffer; + } + + lw = ((float)ivilayer->prop.dest_width / (float)ivilayer->prop.source_width ); + sw = ((float)ivisurf->prop.dest_width / (float)ivisurf->prop.source_width ); + lh = ((float)ivilayer->prop.dest_height / (float)ivilayer->prop.source_height); + sh = ((float)ivisurf->prop.dest_height / (float)ivisurf->prop.source_height ); + 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) { + struct weston_view *tmpview; + 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++; + + wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) { + if (tmpview != NULL) { + break; + } + } + + if (tmpview != NULL) { + weston_view_geometry_dirty(tmpview); + } + + 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->screen_list, link) { + wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) { + wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) { + update_prop(ivilayer, ivisurf); + } + } + } +} + +static void +commit_surface_list(struct ivi_layout *layout) +{ + struct ivi_layout_surface *ivisurf = NULL; + int32_t dest_x = 0; + int32_t dest_y = 0; + int32_t dest_width = 0; + int32_t dest_height = 0; + int32_t configured = 0; + + wl_list_for_each(ivisurf, &layout->surface_list, link) { + if(ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEFAULT) { + dest_x = ivisurf->prop.dest_x; + dest_y = ivisurf->prop.dest_y; + dest_width = ivisurf->prop.dest_width; + dest_height = ivisurf->prop.dest_height; + + ivi_layout_transition_move_resize_view(ivisurf, + ivisurf->pending.prop.dest_x, + ivisurf->pending.prop.dest_y, + ivisurf->pending.prop.dest_width, + ivisurf->pending.prop.dest_height, + ivisurf->pending.prop.transition_duration); + + if(ivisurf->pending.prop.visibility) { + ivi_layout_transition_visibility_on(ivisurf, ivisurf->pending.prop.transition_duration); + } else { + ivi_layout_transition_visibility_off(ivisurf, ivisurf->pending.prop.transition_duration); + } + + ivisurf->prop = ivisurf->pending.prop; + ivisurf->prop.dest_x = dest_x; + ivisurf->prop.dest_y = dest_y; + ivisurf->prop.dest_width = dest_width; + ivisurf->prop.dest_height = dest_height; + ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + + } else if(ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEST_RECT_ONLY){ + dest_x = ivisurf->prop.dest_x; + dest_y = ivisurf->prop.dest_y; + dest_width = ivisurf->prop.dest_width; + dest_height = ivisurf->prop.dest_height; + + ivi_layout_transition_move_resize_view(ivisurf, + ivisurf->pending.prop.dest_x, + ivisurf->pending.prop.dest_y, + ivisurf->pending.prop.dest_width, + ivisurf->pending.prop.dest_height, + ivisurf->pending.prop.transition_duration); + + ivisurf->prop = ivisurf->pending.prop; + ivisurf->prop.dest_x = dest_x; + ivisurf->prop.dest_y = dest_y; + ivisurf->prop.dest_width = dest_width; + ivisurf->prop.dest_height = dest_height; + + ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + + } else if(ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY){ + configured = 0; + if(ivisurf->pending.prop.visibility) { + ivi_layout_transition_visibility_on(ivisurf, ivisurf->pending.prop.transition_duration); + } else { + ivi_layout_transition_visibility_off(ivisurf, ivisurf->pending.prop.transition_duration); + } + + if (ivisurf->prop.dest_width != ivisurf->pending.prop.dest_width || + ivisurf->prop.dest_height != ivisurf->pending.prop.dest_height) { + configured = 1; + } + + ivisurf->prop = ivisurf->pending.prop; + ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + + if (configured && !is_surface_transition(ivisurf)) + wl_signal_emit(&ivisurf->configured, ivisurf); + } else { + configured = 0; + if (ivisurf->prop.dest_width != ivisurf->pending.prop.dest_width || + ivisurf->prop.dest_height != ivisurf->pending.prop.dest_height) { + configured = 1; + } + + ivisurf->prop = ivisurf->pending.prop; + ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + + if (configured && !is_surface_transition(ivisurf)) + wl_signal_emit(&ivisurf->configured, ivisurf); + } + } +} + +static void +commit_layer_list(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->layer_list, link) { + if(ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_MOVE) { + ivi_layout_transition_move_layer(ivilayer, ivilayer->pending.prop.dest_x, ivilayer->pending.prop.dest_y, ivilayer->pending.prop.transition_duration); + } else if(ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_FADE) { + ivi_layout_transition_fade_layer(ivilayer,ivilayer->pending.prop.is_fade_in, + ivilayer->pending.prop.start_alpha,ivilayer->pending.prop.end_alpha, + NULL, NULL, + ivilayer->pending.prop.transition_duration); + } + ivilayer->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + + ivilayer->prop = ivilayer->pending.prop; + + if (!(ivilayer->event_mask & + (IVI_NOTIFICATION_ADD | IVI_NOTIFICATION_REMOVE)) ) { + continue; + } + + if (ivilayer->event_mask & IVI_NOTIFICATION_REMOVE) { + wl_list_for_each_safe(ivisurf, next, + &ivilayer->order.surface_list, 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); + ivisurf->event_mask |= IVI_NOTIFICATION_REMOVE; + } + + wl_list_init(&ivilayer->order.surface_list); + } + + if (ivilayer->event_mask & IVI_NOTIFICATION_ADD) { + wl_list_for_each_safe(ivisurf, next, + &ivilayer->order.surface_list, 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.surface_list); + wl_list_for_each(ivisurf, &ivilayer->pending.surface_list, + 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.surface_list, + &ivisurf->order.link); + add_ordersurface_to_layer(ivisurf, ivilayer); + ivisurf->event_mask |= IVI_NOTIFICATION_ADD; + } + } + } +} + +static void +commit_screen_list(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->screen_list, link) { + if (iviscrn->event_mask & IVI_NOTIFICATION_REMOVE) { + wl_list_for_each_safe(ivilayer, next, + &iviscrn->order.layer_list, 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); + ivilayer->event_mask |= IVI_NOTIFICATION_REMOVE; + } + } + + if (iviscrn->event_mask & IVI_NOTIFICATION_ADD) { + wl_list_for_each_safe(ivilayer, next, + &iviscrn->order.layer_list, 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.layer_list); + wl_list_for_each(ivilayer, &iviscrn->pending.layer_list, + pending.link) { + wl_list_insert(&iviscrn->order.layer_list, + &ivilayer->order.link); + add_orderlayer_to_screen(ivilayer, iviscrn); + ivilayer->event_mask |= IVI_NOTIFICATION_ADD; + } + } + + iviscrn->event_mask = 0; + + /* Clear view list of layout ivi_layer */ + wl_list_init(&layout->layout_layer.view_list.link); + + wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) { + if (ivilayer->prop.visibility == false) + continue; + + wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) { + struct weston_view *tmpview = NULL; + wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) { + if (tmpview != NULL) { + break; + } + } + + if (ivisurf->prop.visibility == false) + continue; + if (ivisurf->surface == NULL || tmpview == NULL) + continue; + + weston_layer_entry_insert(&layout->layout_layer.view_list, + &tmpview->layer_link); + + ivisurf->surface->output = iviscrn->output; + } + } + + break; + } +} + +static void +commit_transition(struct ivi_layout* layout) +{ + if(wl_list_empty(&layout->pending_transition_list)){ + return; + } + + wl_list_insert_list(&layout->transitions->transition_list, + &layout->pending_transition_list); + + wl_list_init(&layout->pending_transition_list); + + wl_event_source_timer_update(layout->transitions->event_source, 1); +} + +static void +send_surface_prop(struct ivi_layout_surface *ivisurf) +{ + wl_signal_emit(&ivisurf->property_changed, ivisurf); + ivisurf->event_mask = 0; +} + +static void +send_layer_prop(struct ivi_layout_layer *ivilayer) +{ + wl_signal_emit(&ivilayer->property_changed, ivilayer); + 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_reverse(ivilayer, &layout->layer_list, link) { + send_layer_prop(ivilayer); + } + + wl_list_for_each_reverse(ivisurf, &layout->surface_list, link) { + send_surface_prop(ivisurf); + } +} + +static void +clear_surface_pending_list(struct ivi_layout_layer *ivilayer) +{ + struct ivi_layout_surface *surface_link = NULL; + struct ivi_layout_surface *surface_next = NULL; + + wl_list_for_each_safe(surface_link, surface_next, + &ivilayer->pending.surface_list, pending.link) { + if (!wl_list_empty(&surface_link->pending.link)) { + wl_list_remove(&surface_link->pending.link); + } + + wl_list_init(&surface_link->pending.link); + } + + ivilayer->event_mask |= IVI_NOTIFICATION_REMOVE; +} + +static void +clear_surface_order_list(struct ivi_layout_layer *ivilayer) +{ + struct ivi_layout_surface *surface_link = NULL; + struct ivi_layout_surface *surface_next = NULL; + + wl_list_for_each_safe(surface_link, surface_next, + &ivilayer->order.surface_list, order.link) { + if (!wl_list_empty(&surface_link->order.link)) { + wl_list_remove(&surface_link->order.link); + } + + wl_list_init(&surface_link->order.link); + } + + ivilayer->event_mask |= IVI_NOTIFICATION_REMOVE; +} + +static void +layer_created(struct wl_listener *listener, void *data) +{ + struct ivi_layout_layer *ivilayer = data; + + struct listener_layout_notification *notification = + container_of(listener, + struct listener_layout_notification, + listener); + + struct ivi_layout_notification_callback *created_callback = + notification->userdata; + + ((layer_create_notification_func)created_callback->callback) + (ivilayer, created_callback->data); +} + +static void +layer_removed(struct wl_listener *listener, void *data) +{ + struct ivi_layout_layer *ivilayer = data; + + struct listener_layout_notification *notification = + container_of(listener, + struct listener_layout_notification, + listener); + + struct ivi_layout_notification_callback *removed_callback = + notification->userdata; + + ((layer_remove_notification_func)removed_callback->callback) + (ivilayer, removed_callback->data); +} + +static void +layer_prop_changed(struct wl_listener *listener, void *data) +{ + struct ivi_layout_layer *ivilayer = data; + + struct listener_layout_notification *layout_listener = + container_of(listener, + struct listener_layout_notification, + listener); + + struct ivi_layout_notification_callback *prop_callback = + layout_listener->userdata; + + ((layer_property_notification_func)prop_callback->callback) + (ivilayer, &ivilayer->prop, ivilayer->event_mask, prop_callback->data); +} + +static void +surface_created(struct wl_listener *listener, void *data) +{ + struct ivi_layout_surface *ivisurface = data; + + struct listener_layout_notification *notification = + container_of(listener, + struct listener_layout_notification, + listener); + + struct ivi_layout_notification_callback *created_callback = + notification->userdata; + + ((surface_create_notification_func)created_callback->callback) + (ivisurface, created_callback->data); +} + +static void +surface_removed(struct wl_listener *listener, void *data) +{ + struct ivi_layout_surface *ivisurface = data; + + struct listener_layout_notification *notification = + container_of(listener, + struct listener_layout_notification, + listener); + + struct ivi_layout_notification_callback *removed_callback = + notification->userdata; + + ((surface_remove_notification_func)removed_callback->callback) + (ivisurface, removed_callback->data); +} + +static void +surface_prop_changed(struct wl_listener *listener, void *data) +{ + struct ivi_layout_surface *ivisurf = data; + + struct listener_layout_notification *layout_listener = + container_of(listener, + struct listener_layout_notification, + listener); + + struct ivi_layout_notification_callback *prop_callback = + layout_listener->userdata; + + ((surface_property_notification_func)prop_callback->callback) + (ivisurf, &ivisurf->prop, ivisurf->event_mask, prop_callback->data); + + ivisurf->event_mask = 0; +} + +static void +surface_configure_changed(struct wl_listener *listener, + void *data) +{ + struct ivi_layout_surface *ivisurface = data; + + struct listener_layout_notification *notification = + container_of(listener, + struct listener_layout_notification, + listener); + + struct ivi_layout_notification_callback *configure_changed_callback = + notification->userdata; + + ((surface_configure_notification_func)configure_changed_callback->callback) + (ivisurface, configure_changed_callback->data); +} + +static int32_t +add_notification(struct wl_signal *signal, + wl_notify_func_t callback, + void *userdata) +{ + struct listener_layout_notification *notification = NULL; + + notification = malloc(sizeof *notification); + if (notification == NULL) { + weston_log("fails to allocate memory\n"); + free(userdata); + return IVI_FAILED; + } + + notification->listener.notify = callback; + notification->userdata = userdata; + + wl_signal_add(signal, ¬ification->listener); + + return IVI_SUCCEEDED; +} + +static void +remove_notification(struct wl_list *listener_list, void *callback, void *userdata) +{ + struct wl_listener *listener = NULL; + struct wl_listener *next = NULL; + + wl_list_for_each_safe(listener, next, listener_list, link) { + struct listener_layout_notification *notification = + container_of(listener, + struct listener_layout_notification, + listener); + + struct ivi_layout_notification_callback *notification_callback = + notification->userdata; + + if ((notification_callback->callback != callback) || + (notification_callback->data != userdata)) { + continue; + } + + if (!wl_list_empty(&listener->link)) { + wl_list_remove(&listener->link); + } + + free(notification->userdata); + free(notification); + } +} + +static void +remove_all_notification(struct wl_list *listener_list) +{ + struct wl_listener *listener = NULL; + struct wl_listener *next = NULL; + + wl_list_for_each_safe(listener, next, listener_list, link) { + struct listener_layout_notification *notification = NULL; + if (!wl_list_empty(&listener->link)) { + wl_list_remove(&listener->link); + } + + notification = + container_of(listener, + struct listener_layout_notification, + listener); + + free(notification->userdata); + free(notification); + } +} + +/** + * 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_add_notification_create_layer(layer_create_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_notification_callback *created_callback = NULL; + + if (callback == NULL) { + weston_log("ivi_layout_add_notification_create_layer: invalid argument\n"); + return IVI_FAILED; + } + + created_callback = malloc(sizeof *created_callback); + if (created_callback == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + created_callback->callback = callback; + created_callback->data = userdata; + + return add_notification(&layout->layer_notification.created, + layer_created, + created_callback); +} + +WL_EXPORT void +ivi_layout_remove_notification_create_layer(layer_create_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + remove_notification(&layout->layer_notification.created.listener_list, callback, userdata); +} + +WL_EXPORT int32_t +ivi_layout_add_notification_remove_layer(layer_remove_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_notification_callback *removed_callback = NULL; + + if (callback == NULL) { + weston_log("ivi_layout_add_notification_remove_layer: invalid argument\n"); + return IVI_FAILED; + } + + removed_callback = malloc(sizeof *removed_callback); + if (removed_callback == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + removed_callback->callback = callback; + removed_callback->data = userdata; + return add_notification(&layout->layer_notification.removed, + layer_removed, + removed_callback); +} + +WL_EXPORT void +ivi_layout_remove_notification_remove_layer(layer_remove_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + remove_notification(&layout->layer_notification.removed.listener_list, callback, userdata); +} + +WL_EXPORT int32_t +ivi_layout_add_notification_create_surface(surface_create_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_notification_callback *created_callback = NULL; + + if (callback == NULL) { + weston_log("ivi_layout_add_notification_create_surface: invalid argument\n"); + return IVI_FAILED; + } + + created_callback = malloc(sizeof *created_callback); + if (created_callback == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + created_callback->callback = callback; + created_callback->data = userdata; + + return add_notification(&layout->surface_notification.created, + surface_created, + created_callback); +} + +WL_EXPORT void +ivi_layout_remove_notification_create_surface(surface_create_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + remove_notification(&layout->surface_notification.created.listener_list, callback, userdata); +} + +WL_EXPORT int32_t +ivi_layout_add_notification_remove_surface(surface_remove_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_notification_callback *removed_callback = NULL; + + if (callback == NULL) { + weston_log("ivi_layout_add_notification_remove_surface: invalid argument\n"); + return IVI_FAILED; + } + + removed_callback = malloc(sizeof *removed_callback); + if (removed_callback == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + removed_callback->callback = callback; + removed_callback->data = userdata; + + return add_notification(&layout->surface_notification.removed, + surface_removed, + removed_callback); +} + +WL_EXPORT void +ivi_layout_remove_notification_remove_surface(surface_remove_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + remove_notification(&layout->surface_notification.removed.listener_list, callback, userdata); +} + +WL_EXPORT int32_t +ivi_layout_add_notification_configure_surface(surface_configure_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_notification_callback *configure_changed_callback = NULL; + if (callback == NULL) { + weston_log("ivi_layout_add_notification_configure_surface: invalid argument\n"); + return IVI_FAILED; + } + + configure_changed_callback = malloc(sizeof *configure_changed_callback); + if (configure_changed_callback == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + configure_changed_callback->callback = callback; + configure_changed_callback->data = userdata; + + return add_notification(&layout->surface_notification.configure_changed, + surface_configure_changed, + configure_changed_callback); +} + +WL_EXPORT void +ivi_layout_remove_notification_configure_surface(surface_configure_notification_func callback, + void *userdata) +{ + struct ivi_layout *layout = get_instance(); + remove_notification(&layout->surface_notification.configure_changed.listener_list, callback, userdata); +} + +WL_EXPORT uint32_t +ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf) +{ + return ivisurf->id_surface; +} + +WL_EXPORT uint32_t +ivi_layout_get_id_of_layer(struct ivi_layout_layer *ivilayer) +{ + return ivilayer->id_layer; +} + +struct ivi_layout_layer * +ivi_layout_get_layer_from_id(uint32_t id_layer) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_layer *ivilayer = NULL; + + wl_list_for_each(ivilayer, &layout->layer_list, link) { + if (ivilayer->id_layer == id_layer) { + return ivilayer; + } + } + + return NULL; +} + +WL_EXPORT struct ivi_layout_surface * +ivi_layout_get_surface_from_id(uint32_t id_surface) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_surface *ivisurf = NULL; + + wl_list_for_each(ivisurf, &layout->surface_list, link) { + if (ivisurf->id_surface == id_surface) { + return ivisurf; + } + } + + return NULL; +} + +WL_EXPORT struct ivi_layout_screen * +ivi_layout_get_screen_from_id(uint32_t id_screen) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_screen *iviscrn = NULL; + + wl_list_for_each(iviscrn, &layout->screen_list, link) { +//FIXME : select iviscrn from screen_list by id_screen + return iviscrn; + break; + } + + return NULL; +} + +WL_EXPORT int32_t +ivi_layout_get_screen_resolution(struct ivi_layout_screen *iviscrn, + int32_t *pWidth, int32_t *pHeight) +{ + struct weston_output *output = NULL; + + if (pWidth == NULL || pHeight == NULL) { + weston_log("ivi_layout_get_screen_resolution: invalid argument\n"); + return IVI_FAILED; + } + + output = iviscrn->output; + *pWidth = output->current_mode->width; + *pHeight = output->current_mode->height; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_surface_add_notification(struct ivi_layout_surface *ivisurf, + surface_property_notification_func callback, + void *userdata) +{ + struct listener_layout_notification* notification = NULL; + struct ivi_layout_notification_callback *prop_callback = NULL; + + if (ivisurf == NULL || callback == NULL) { + weston_log("ivi_layout_surface_add_notification: invalid argument\n"); + return IVI_FAILED; + } + + notification = malloc(sizeof *notification); + if (notification == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + prop_callback = malloc(sizeof *prop_callback); + if (prop_callback == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + prop_callback->callback = callback; + prop_callback->data = userdata; + + notification->listener.notify = surface_prop_changed; + notification->userdata = prop_callback; + + wl_signal_add(&ivisurf->property_changed, ¬ification->listener); + + return IVI_SUCCEEDED; +} + +WL_EXPORT void +ivi_layout_surface_remove_notification(struct ivi_layout_surface *ivisurf) +{ + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_remove_notification: invalid argument\n"); + return; + } + + remove_all_notification(&ivisurf->property_changed.listener_list); +} + +static void +remove_configured_listener(struct ivi_layout_surface *ivisurf) +{ + struct wl_listener *link = NULL; + struct wl_listener *next = NULL; + + wl_list_for_each_safe(link, next, &ivisurf->configured.listener_list, link) { + wl_list_remove(&link->link); + } +} + +void +ivi_layout_surface_remove(struct ivi_layout_surface *ivisurf) +{ + struct ivi_layout *layout = get_instance(); + + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_remove: invalid argument\n"); + return; + } + + 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_signal_emit(&layout->surface_notification.removed, ivisurf); + + remove_configured_listener(ivisurf); + + ivi_layout_surface_remove_notification(ivisurf); + + free(ivisurf); +} + +WL_EXPORT const struct ivi_layout_layer_properties * +ivi_layout_get_properties_of_layer(struct ivi_layout_layer *ivilayer) +{ + if (ivilayer == NULL) { + weston_log("ivi_layout_get_properties_of_layer: invalid argument\n"); + return NULL; + } + + return &ivilayer->prop; +} + +WL_EXPORT int32_t +ivi_layout_get_screens(int32_t *pLength, struct ivi_layout_screen ***ppArray) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_screen *iviscrn = NULL; + int32_t length = 0; + int32_t n = 0; + + if (pLength == NULL || ppArray == NULL) { + weston_log("ivi_layout_get_screens: invalid argument\n"); + return IVI_FAILED; + } + + length = wl_list_length(&layout->screen_list); + + if (length != 0){ + /* the Array must be free by module which called this function */ + *ppArray = calloc(length, sizeof(struct ivi_layout_screen *)); + if (*ppArray == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + wl_list_for_each(iviscrn, &layout->screen_list, link) { + (*ppArray)[n++] = iviscrn; + } + } + + *pLength = length; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_get_screens_under_layer(struct ivi_layout_layer *ivilayer, + int32_t *pLength, + struct ivi_layout_screen ***ppArray) +{ + struct link_screen *link_scrn = NULL; + int32_t length = 0; + int32_t n = 0; + + if (ivilayer == NULL || pLength == NULL || ppArray == NULL) { + weston_log("ivi_layout_get_screens_under_layer: invalid argument\n"); + return IVI_FAILED; + } + + length = wl_list_length(&ivilayer->screen_list); + + if (length != 0){ + /* the Array must be free by module which called this function */ + *ppArray = calloc(length, sizeof(struct ivi_layout_screen *)); + if (*ppArray == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + wl_list_for_each(link_scrn, &ivilayer->screen_list, link) { + (*ppArray)[n++] = link_scrn->iviscrn; + } + } + + *pLength = length; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_get_layers(int32_t *pLength, struct ivi_layout_layer ***ppArray) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_layer *ivilayer = NULL; + int32_t length = 0; + int32_t n = 0; + + if (pLength == NULL || ppArray == NULL) { + weston_log("ivi_layout_get_layers: invalid argument\n"); + return IVI_FAILED; + } + + length = wl_list_length(&layout->layer_list); + + if (length != 0){ + /* the Array must be free by module which called this function */ + *ppArray = calloc(length, sizeof(struct ivi_layout_layer *)); + if (*ppArray == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + wl_list_for_each(ivilayer, &layout->layer_list, link) { + (*ppArray)[n++] = ivilayer; + } + } + + *pLength = length; + + return IVI_SUCCEEDED; +} + +int32_t +ivi_layout_get_layers_on_screen(struct ivi_layout_screen *iviscrn, + int32_t *pLength, + struct ivi_layout_layer ***ppArray) +{ + struct ivi_layout_layer *ivilayer = NULL; + int32_t length = 0; + int32_t n = 0; + + if (iviscrn == NULL || pLength == NULL || ppArray == NULL) { + weston_log("ivi_layout_get_layers_on_screen: invalid argument\n"); + return IVI_FAILED; + } + + length = wl_list_length(&iviscrn->order.layer_list); + + if (length != 0){ + /* the Array must be free by module which called this function */ + *ppArray = calloc(length, sizeof(struct ivi_layout_layer *)); + if (*ppArray == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + wl_list_for_each(ivilayer, &iviscrn->order.layer_list, link) { + (*ppArray)[n++] = ivilayer; + } + } + + *pLength = length; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_get_layers_under_surface(struct ivi_layout_surface *ivisurf, + int32_t *pLength, + struct ivi_layout_layer ***ppArray) +{ + struct link_layer *link_layer = NULL; + int32_t length = 0; + int32_t n = 0; + + if (ivisurf == NULL || pLength == NULL || ppArray == NULL) { + weston_log("ivi_layout_getLayers: invalid argument\n"); + return IVI_FAILED; + } + + length = wl_list_length(&ivisurf->layer_list); + + if (length != 0){ + /* the Array must be free by module which called this function */ + *ppArray = calloc(length, sizeof(struct ivi_layout_layer *)); + if (*ppArray == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + wl_list_for_each(link_layer, &ivisurf->layer_list, link) { + (*ppArray)[n++] = link_layer->ivilayer; + } + } + + *pLength = length; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_get_surfaces(int32_t *pLength, struct ivi_layout_surface ***ppArray) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_surface *ivisurf = NULL; + int32_t length = 0; + int32_t n = 0; + + if (pLength == NULL || ppArray == NULL) { + weston_log("ivi_layout_get_surfaces: invalid argument\n"); + return IVI_FAILED; + } + + length = wl_list_length(&layout->surface_list); + + if (length != 0){ + /* the Array must be free by module which called this function */ + *ppArray = calloc(length, sizeof(struct ivi_layout_surface *)); + if (*ppArray == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + wl_list_for_each(ivisurf, &layout->surface_list, link) { + (*ppArray)[n++] = ivisurf; + } + } + + *pLength = length; + + return IVI_SUCCEEDED; +} + +int32_t +ivi_layout_get_surfaces_on_layer(struct ivi_layout_layer *ivilayer, + int32_t *pLength, + struct ivi_layout_surface ***ppArray) +{ + struct ivi_layout_surface *ivisurf = NULL; + int32_t length = 0; + int32_t n = 0; + + if (ivilayer == NULL || pLength == NULL || ppArray == NULL) { + weston_log("ivi_layout_getSurfaceIDsOnLayer: invalid argument\n"); + return IVI_FAILED; + } + + length = wl_list_length(&ivilayer->order.surface_list); + + if (length != 0) { + /* the Array must be free by module which called this function */ + *ppArray = calloc(length, sizeof(struct ivi_layout_surface *)); + if (*ppArray == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) { + (*ppArray)[n++] = ivisurf; + } + } + + *pLength = length; + + return IVI_SUCCEEDED; +} + +WL_EXPORT struct ivi_layout_layer * +ivi_layout_layer_create_with_dimension(uint32_t id_layer, + int32_t width, int32_t height) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_layer *ivilayer = NULL; + + ivilayer = get_layer(&layout->layer_list, 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_signal_init(&ivilayer->property_changed); + wl_list_init(&ivilayer->screen_list); + wl_list_init(&ivilayer->link_to_surface); + ivilayer->layout = layout; + ivilayer->id_layer = id_layer; + + init_layer_properties(&ivilayer->prop, width, height); + ivilayer->event_mask = 0; + + wl_list_init(&ivilayer->pending.surface_list); + wl_list_init(&ivilayer->pending.link); + ivilayer->pending.prop = ivilayer->prop; + + wl_list_init(&ivilayer->order.surface_list); + wl_list_init(&ivilayer->order.link); + + wl_list_insert(&layout->layer_list, &ivilayer->link); + + wl_signal_emit(&layout->layer_notification.created, ivilayer); + + return ivilayer; +} + +WL_EXPORT void +ivi_layout_layer_remove(struct ivi_layout_layer *ivilayer) +{ + struct ivi_layout *layout = get_instance(); + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_remove: invalid argument\n"); + return; + } + + wl_signal_emit(&layout->layer_notification.removed, ivilayer); + + clear_surface_pending_list(ivilayer); + clear_surface_order_list(ivilayer); + + 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); + ivi_layout_layer_remove_notification(ivilayer); + + free(ivilayer); +} + +WL_EXPORT int32_t +ivi_layout_layer_set_visibility(struct ivi_layout_layer *ivilayer, + bool newVisibility) +{ + struct ivi_layout_layer_properties *prop = NULL; + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_set_visibility: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivilayer->pending.prop; + prop->visibility = newVisibility; + + ivilayer->event_mask |= IVI_NOTIFICATION_VISIBILITY; + + return IVI_SUCCEEDED; +} + +bool +ivi_layout_layer_get_visibility(struct ivi_layout_layer *ivilayer) +{ + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_get_visibility: invalid argument\n"); + return false; + } + + return ivilayer->prop.visibility; +} + +WL_EXPORT int32_t +ivi_layout_layer_set_opacity(struct ivi_layout_layer *ivilayer, + wl_fixed_t opacity) +{ + struct ivi_layout_layer_properties *prop = NULL; + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_set_opacity: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivilayer->pending.prop; + prop->opacity = opacity; + + ivilayer->event_mask |= IVI_NOTIFICATION_OPACITY; + + return IVI_SUCCEEDED; +} + +WL_EXPORT wl_fixed_t +ivi_layout_layer_get_opacity(struct ivi_layout_layer *ivilayer) +{ + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_get_opacity: invalid argument\n"); + return wl_fixed_from_double(0.0); + } + + return ivilayer->prop.opacity; +} + +WL_EXPORT int32_t +ivi_layout_layer_set_source_rectangle(struct ivi_layout_layer *ivilayer, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + struct ivi_layout_layer_properties *prop = NULL; + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_set_source_rectangle: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivilayer->pending.prop; + prop->source_x = x; + prop->source_y = y; + prop->source_width = width; + prop->source_height = height; + + ivilayer->event_mask |= IVI_NOTIFICATION_SOURCE_RECT; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_layer_set_destination_rectangle(struct ivi_layout_layer *ivilayer, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + struct ivi_layout_layer_properties *prop = NULL; + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_set_destination_rectangle: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivilayer->pending.prop; + prop->dest_x = x; + prop->dest_y = y; + prop->dest_width = width; + prop->dest_height = height; + + ivilayer->event_mask |= IVI_NOTIFICATION_DEST_RECT; + + return IVI_SUCCEEDED; +} + +int32_t +ivi_layout_layer_get_dimension(struct ivi_layout_layer *ivilayer, + int32_t *dest_width, int32_t *dest_height) +{ + if (ivilayer == NULL || dest_width == NULL || dest_height == NULL) { + weston_log("ivi_layout_layer_get_dimension: invalid argument\n"); + return IVI_FAILED; + } + + *dest_width = ivilayer->prop.dest_width; + *dest_height = ivilayer->prop.dest_height; + + return IVI_SUCCEEDED; +} + +int32_t +ivi_layout_layer_set_dimension(struct ivi_layout_layer *ivilayer, + int32_t dest_width, int32_t dest_height) +{ + struct ivi_layout_layer_properties *prop = NULL; + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_set_dimension: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivilayer->pending.prop; + + prop->dest_width = dest_width; + prop->dest_height = dest_height; + + ivilayer->event_mask |= IVI_NOTIFICATION_DIMENSION; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_layer_get_position(struct ivi_layout_layer *ivilayer, + int32_t *dest_x, int32_t *dest_y) +{ + if (ivilayer == NULL || dest_x == NULL || dest_y == NULL) { + weston_log("ivi_layout_layer_get_position: invalid argument\n"); + return IVI_FAILED; + } + + *dest_x = ivilayer->prop.dest_x; + *dest_y = ivilayer->prop.dest_y; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_layer_set_position(struct ivi_layout_layer *ivilayer, + int32_t dest_x, int32_t dest_y) +{ + struct ivi_layout_layer_properties *prop = NULL; + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_set_position: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivilayer->pending.prop; + prop->dest_x = dest_x; + prop->dest_y = dest_y; + + ivilayer->event_mask |= IVI_NOTIFICATION_POSITION; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_layer_set_orientation(struct ivi_layout_layer *ivilayer, + enum wl_output_transform orientation) +{ + struct ivi_layout_layer_properties *prop = NULL; + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_set_orientation: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivilayer->pending.prop; + prop->orientation = orientation; + + ivilayer->event_mask |= IVI_NOTIFICATION_ORIENTATION; + + return IVI_SUCCEEDED; +} + +enum wl_output_transform +ivi_layout_layer_get_orientation(struct ivi_layout_layer *ivilayer) +{ + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_get_orientation: invalid argument\n"); + return 0; + } + + return ivilayer->prop.orientation; +} + +WL_EXPORT int32_t +ivi_layout_layer_set_render_order(struct ivi_layout_layer *ivilayer, + struct ivi_layout_surface **pSurface, + int32_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; + int32_t i = 0; + + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_set_render_order: invalid argument\n"); + return IVI_FAILED; + } + + if (pSurface == NULL) { + wl_list_for_each_safe(ivisurf, next, &ivilayer->pending.surface_list, pending.link) { + if (!wl_list_empty(&ivisurf->pending.link)) { + wl_list_remove(&ivisurf->pending.link); + } + + wl_list_init(&ivisurf->pending.link); + } + ivilayer->event_mask |= IVI_NOTIFICATION_REMOVE; + return IVI_SUCCEEDED; + } + + for (i = 0; i < number; i++) { + id_surface = &pSurface[i]->id_surface; + + wl_list_for_each_safe(ivisurf, next, &layout->surface_list, 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.surface_list, + &ivisurf->pending.link); + break; + } + } + + ivilayer->event_mask |= IVI_NOTIFICATION_ADD; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_surface_set_visibility(struct ivi_layout_surface *ivisurf, + bool newVisibility) +{ + struct ivi_layout_surface_properties *prop = NULL; + + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_set_visibility: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivisurf->pending.prop; + prop->visibility = newVisibility; + + ivisurf->event_mask |= IVI_NOTIFICATION_VISIBILITY; + + return IVI_SUCCEEDED; +} + +WL_EXPORT bool +ivi_layout_surface_get_visibility(struct ivi_layout_surface *ivisurf) +{ + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_get_visibility: invalid argument\n"); + return false; + } + + return ivisurf->prop.visibility; +} + +WL_EXPORT int32_t +ivi_layout_surface_set_opacity(struct ivi_layout_surface *ivisurf, + wl_fixed_t opacity) +{ + struct ivi_layout_surface_properties *prop = NULL; + + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_set_opacity: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivisurf->pending.prop; + prop->opacity = opacity; + + ivisurf->event_mask |= IVI_NOTIFICATION_OPACITY; + + return IVI_SUCCEEDED; +} + +WL_EXPORT wl_fixed_t +ivi_layout_surface_get_opacity(struct ivi_layout_surface *ivisurf) +{ + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_get_opacity: invalid argument\n"); + return wl_fixed_from_double(0.0); + } + + return ivisurf->prop.opacity; +} + +WL_EXPORT int32_t +ivi_layout_surface_set_destination_rectangle(struct ivi_layout_surface *ivisurf, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + struct ivi_layout_surface_properties *prop = NULL; + + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_set_destination_rectangle: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivisurf->pending.prop; + prop->start_x = prop->dest_x; + prop->start_y = prop->dest_y; + prop->dest_x = x; + prop->dest_y = y; + prop->start_width = prop->dest_width; + prop->start_height = prop->dest_height; + prop->dest_width = width; + prop->dest_height = height; + + ivisurf->event_mask |= IVI_NOTIFICATION_DEST_RECT; + + return IVI_SUCCEEDED; +} + +int32_t +ivi_layout_surface_set_dimension(struct ivi_layout_surface *ivisurf, + int32_t dest_width, int32_t dest_height) +{ + struct ivi_layout_surface_properties *prop = NULL; + + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_set_dimension: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivisurf->pending.prop; + prop->dest_width = dest_width; + prop->dest_height = dest_height; + + ivisurf->event_mask |= IVI_NOTIFICATION_DIMENSION; + + return IVI_SUCCEEDED; +} + +int32_t +ivi_layout_surface_get_dimension(struct ivi_layout_surface *ivisurf, + int32_t *dest_width, int32_t *dest_height) +{ + if (ivisurf == NULL || dest_width == NULL || dest_height == NULL) { + weston_log("ivi_layout_surface_get_dimension: invalid argument\n"); + return IVI_FAILED; + } + + *dest_width = ivisurf->prop.dest_width; + *dest_height = ivisurf->prop.dest_height; + + return IVI_SUCCEEDED; +} + +int32_t +ivi_layout_surface_set_position(struct ivi_layout_surface *ivisurf, + int32_t dest_x, int32_t dest_y) +{ + struct ivi_layout_surface_properties *prop = NULL; + + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_set_position: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivisurf->pending.prop; + prop->dest_x = dest_x; + prop->dest_y = dest_y; + + ivisurf->event_mask |= IVI_NOTIFICATION_POSITION; + + return IVI_SUCCEEDED; +} + +int32_t +ivi_layout_surface_get_position(struct ivi_layout_surface *ivisurf, + int32_t *dest_x, int32_t *dest_y) +{ + if (ivisurf == NULL || dest_x == NULL || dest_y == NULL) { + weston_log("ivi_layout_surface_get_position: invalid argument\n"); + return IVI_FAILED; + } + + *dest_x = ivisurf->prop.dest_x; + *dest_y = ivisurf->prop.dest_y; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_surface_set_orientation(struct ivi_layout_surface *ivisurf, + enum wl_output_transform orientation) +{ + struct ivi_layout_surface_properties *prop = NULL; + + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_set_orientation: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivisurf->pending.prop; + prop->orientation = orientation; + + ivisurf->event_mask |= IVI_NOTIFICATION_ORIENTATION; + + return IVI_SUCCEEDED; +} + +enum wl_output_transform +ivi_layout_surface_get_orientation(struct ivi_layout_surface *ivisurf) +{ + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_get_orientation: invalid argument\n"); + return 0; + } + + return ivisurf->prop.orientation; +} + +WL_EXPORT int32_t +ivi_layout_screen_add_layer(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_screen_add_layer: invalid argument\n"); + return IVI_FAILED; + } + + is_layer_in_scrn = is_layer_in_screen(addlayer, iviscrn); + if (is_layer_in_scrn == 1) { + weston_log("ivi_layout_screen_add_layer: addlayer is already available\n"); + return IVI_SUCCEEDED; + } + + wl_list_for_each_safe(ivilayer, next, &layout->layer_list, 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.layer_list, + &ivilayer->pending.link); + break; + } + } + + iviscrn->event_mask |= IVI_NOTIFICATION_ADD; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_screen_set_render_order(struct ivi_layout_screen *iviscrn, + struct ivi_layout_layer **pLayer, + const int32_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; + int32_t i = 0; + + if (iviscrn == NULL) { + weston_log("ivi_layout_screen_set_render_order: invalid argument\n"); + return IVI_FAILED; + } + + wl_list_for_each_safe(ivilayer, next, + &iviscrn->pending.layer_list, pending.link) { + wl_list_init(&ivilayer->pending.link); + } + + wl_list_init(&iviscrn->pending.layer_list); + + if (pLayer == NULL) { + wl_list_for_each_safe(ivilayer, next, &iviscrn->pending.layer_list, pending.link) { + if (!wl_list_empty(&ivilayer->pending.link)) { + wl_list_remove(&ivilayer->pending.link); + } + + wl_list_init(&ivilayer->pending.link); + } + + iviscrn->event_mask |= IVI_NOTIFICATION_REMOVE; + return IVI_SUCCEEDED; + } + + for (i = 0; i < number; i++) { + id_layer = &pLayer[i]->id_layer; + wl_list_for_each(ivilayer, &layout->layer_list, 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.layer_list, + &ivilayer->pending.link); + break; + } + } + + iviscrn->event_mask |= IVI_NOTIFICATION_ADD; + + return IVI_SUCCEEDED; +} + +WL_EXPORT struct weston_output * +ivi_layout_screen_get_output(struct ivi_layout_screen *iviscrn) +{ + return iviscrn->output; +} + +/** + * This function is used by the additional ivi-module because of dumping ivi_surface sceenshot. + * The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management. + * This function is used to get the result of drawing by clients. + */ +WL_EXPORT struct weston_surface * +ivi_layout_surface_get_weston_surface(struct ivi_layout_surface *ivisurf) +{ + return ivisurf != NULL ? ivisurf->surface : NULL; +} + +/** + * This function is used by the additional ivi-module because of dumping ivi_surface sceenshot. + * The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management. + * This function is used to get the region and the stride. + */ +WL_EXPORT int32_t +ivi_layout_surface_get_size(struct ivi_layout_surface *ivisurf, int32_t *width, int32_t *height, int32_t *stride) +{ + if (ivisurf == NULL) { + return IVI_FAILED; + } + + if (width != NULL) { + *width = ivisurf->prop.source_width; + } + + if (height != NULL) { + *height = ivisurf->prop.source_height; + } + + if (stride != NULL && + ivisurf->surface->buffer_ref.buffer != NULL && + ivisurf->surface->buffer_ref.buffer->shm_buffer != NULL) { + *stride = wl_shm_buffer_get_stride(ivisurf->surface->buffer_ref.buffer->shm_buffer); + } + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_layer_add_notification(struct ivi_layout_layer *ivilayer, + layer_property_notification_func callback, + void *userdata) +{ + struct ivi_layout_notification_callback *prop_callback = NULL; + + if (ivilayer == NULL || callback == NULL) { + weston_log("ivi_layout_layer_add_notification: invalid argument\n"); + return IVI_FAILED; + } + + prop_callback = malloc(sizeof *prop_callback); + if (prop_callback == NULL) { + weston_log("fails to allocate memory\n"); + return IVI_FAILED; + } + + prop_callback->callback = callback; + prop_callback->data = userdata; + + return add_notification(&ivilayer->property_changed, + layer_prop_changed, + prop_callback); +} + +WL_EXPORT void +ivi_layout_layer_remove_notification(struct ivi_layout_layer *ivilayer) +{ + if (ivilayer == NULL) { + weston_log("ivi_layout_layer_remove_notification: invalid argument\n"); + return; + } + + remove_all_notification(&ivilayer->property_changed.listener_list); +} + +WL_EXPORT const struct ivi_layout_surface_properties * +ivi_layout_get_properties_of_surface(struct ivi_layout_surface *ivisurf) +{ + if (ivisurf == NULL) { + weston_log("ivi_layout_get_properties_of_surface: invalid argument\n"); + return NULL; + } + + return &ivisurf->prop; +} + +WL_EXPORT int32_t +ivi_layout_layer_add_surface(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_layer_add_surface: invalid argument\n"); + return IVI_FAILED; + } + + is_surf_in_layer = is_surface_in_layer(addsurf, ivilayer); + if (is_surf_in_layer == 1) { + weston_log("ivi_layout_layer_add_surface: addsurf is already available\n"); + return IVI_SUCCEEDED; + } + + wl_list_for_each_safe(ivisurf, next, &layout->surface_list, 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.surface_list, + &ivisurf->pending.link); + break; + } + } + + ivilayer->event_mask |= IVI_NOTIFICATION_ADD; + + return IVI_SUCCEEDED; +} + +WL_EXPORT void +ivi_layout_layer_remove_surface(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_layer_remove_surface: invalid argument\n"); + return; + } + + wl_list_for_each_safe(ivisurf, next, + &ivilayer->pending.surface_list, 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; + } + } + + remsurf->event_mask |= IVI_NOTIFICATION_REMOVE; +} + +WL_EXPORT int32_t +ivi_layout_surface_set_source_rectangle(struct ivi_layout_surface *ivisurf, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + struct ivi_layout_surface_properties *prop = NULL; + + if (ivisurf == NULL) { + weston_log("ivi_layout_surface_set_source_rectangle: invalid argument\n"); + return IVI_FAILED; + } + + prop = &ivisurf->pending.prop; + prop->source_x = x; + prop->source_y = y; + prop->source_width = width; + prop->source_height = height; + + ivisurf->event_mask |= IVI_NOTIFICATION_SOURCE_RECT; + + return IVI_SUCCEEDED; +} + +WL_EXPORT int32_t +ivi_layout_commit_changes(void) +{ + struct ivi_layout *layout = get_instance(); + + commit_surface_list(layout); + commit_layer_list(layout); + commit_screen_list(layout); + + commit_transition(layout); + + commit_changes(layout); + send_prop(layout); + weston_compositor_schedule_repaint(layout->compositor); + + return IVI_SUCCEEDED; +} + +/***called from ivi-shell**/ +static struct weston_view * +ivi_layout_get_weston_view(struct ivi_layout_surface *surface) +{ + struct weston_view *tmpview = NULL; + + if(surface == NULL) + return NULL; + + wl_list_for_each(tmpview, &surface->surface->views, surface_link) + { + if (tmpview != NULL) { + break; + } + } + return tmpview; +} + +static void +ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf, + int32_t width, int32_t height) +{ + struct ivi_layout *layout = get_instance(); + int32_t in_init = 0; + ivisurf->surface->width_from_buffer = width; + ivisurf->surface->height_from_buffer = height; + + if (ivisurf->prop.source_width == 0 || ivisurf->prop.source_height == 0) { + in_init = 1; + } + + /* FIXME: when sourceHeight/Width is used as clipping range in image buffer */ + /* if (ivisurf->prop.sourceWidth == 0 || ivisurf->prop.sourceHeight == 0) { */ + ivisurf->pending.prop.source_width = width; + ivisurf->pending.prop.source_height = height; + ivisurf->prop.source_width = width; + ivisurf->prop.source_height = height; + /* } */ + + ivisurf->event_mask |= IVI_NOTIFICATION_CONFIGURE; + + if (in_init) { + wl_signal_emit(&layout->surface_notification.configure_changed, ivisurf); + } else { + ivi_layout_commit_changes(); + } +} + +WL_EXPORT int32_t +ivi_layout_surface_set_content_observer(struct ivi_layout_surface *ivisurf, + ivi_controller_surface_content_callback callback, + void* userdata) +{ + int32_t ret = IVI_FAILED; + + if (ivisurf != NULL) { + ivisurf->content_observer.callback = callback; + ivisurf->content_observer.userdata = userdata; + ret = IVI_SUCCEEDED; + } + return ret; +} + +static struct ivi_layout_surface* +ivi_layout_surface_create(struct weston_surface *wl_surface, + uint32_t id_surface) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_surface *ivisurf = NULL; + struct weston_view *tmpview = NULL; + + if (wl_surface == NULL) { + weston_log("ivi_layout_surface_create: invalid argument\n"); + return NULL; + } + + ivisurf = get_surface(&layout->surface_list, id_surface); + if (ivisurf != NULL) { + if (ivisurf->surface != NULL) { + weston_log("id_surface(%d) is already created\n", id_surface); + 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_signal_init(&ivisurf->property_changed); + wl_signal_init(&ivisurf->configured); + wl_list_init(&ivisurf->layer_list); + 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); + + tmpview = weston_view_create(wl_surface); + if (tmpview == NULL) { + weston_log("fails to allocate memory\n"); + } + + ivisurf->surface->width_from_buffer = 0; + ivisurf->surface->height_from_buffer = 0; + + 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_surface_properties(&ivisurf->prop); + 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.layer_list); + + wl_list_insert(&layout->surface_list, &ivisurf->link); + + wl_signal_emit(&layout->surface_notification.created, ivisurf); + + return ivisurf; +} + +static void +ivi_layout_init_with_compositor(struct weston_compositor *ec) +{ + struct ivi_layout *layout = get_instance(); + + layout->compositor = ec; + + wl_list_init(&layout->surface_list); + wl_list_init(&layout->layer_list); + wl_list_init(&layout->screen_list); + + wl_signal_init(&layout->layer_notification.created); + wl_signal_init(&layout->layer_notification.removed); + + wl_signal_init(&layout->surface_notification.created); + wl_signal_init(&layout->surface_notification.removed); + wl_signal_init(&layout->surface_notification.configure_changed); + + /* Add layout_layer at the last of weston_compositor.layer_list */ + weston_layer_init(&layout->layout_layer, ec->layer_list.prev); + + create_screen(ec); + + layout->transitions = ivi_layout_transition_set_create(ec); + wl_list_init(&layout->pending_transition_list); +} + + +static void +ivi_layout_surface_add_configured_listener(struct ivi_layout_surface* ivisurf, + struct wl_listener* listener) +{ + wl_signal_add(&ivisurf->configured, listener); +} + +WL_EXPORT struct ivi_layout_interface ivi_layout_interface = { + .get_weston_view = ivi_layout_get_weston_view, + .surface_configure = ivi_layout_surface_configure, + .surface_create = ivi_layout_surface_create, + .init_with_compositor = ivi_layout_init_with_compositor, + .get_surface_dimension = ivi_layout_surface_get_dimension, + .add_surface_configured_listener = ivi_layout_surface_add_configured_listener +}; -- 1.7.9.5