diff options
37 files changed, 741 insertions, 222 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 988fc89..c70f953 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) project(wayland-ivi-extension) +include(GNUInstallDirs) + SET(IVI_EXTENSION_VERSION 2.2.0) SET(ILM_API_VERSION 2.2.0) @@ -46,17 +46,21 @@ Pre-requisite: export LD_LIBRARY_PATH=<your installation path>/lib Start-up Weston: - Example: <your installation path>/bin/weston + Syntax: <your installation path>/bin/weston [wayland_display_to_listen_on] + Example: /usr/bin/weston -Swayland-1 Start-up HMI helper: - Example: <your installation path>/bin/layer-add-surfaces 1000 1 + Syntax: [wayland_display_to_connect_to] <your installation path>/bin/layer-add-surfaces <layer_id> <surface_count> + Example: WAYLAND_DISPLAY=wayland-1 $HOME/bin/layer-add-surfaces 1000 1 EGLWLMockNavigation: - Example: <your installation path>/bin/EGLWLMockNavigation + Syntax: [wayland_display_to_connect_to] <your installation path>/bin/EGLWLMockNavigation + Example: WAYLAND_DISPLAY=wayland-1 $HOME/bin/EGLWLMockNavigation How to test ==================================== 1. Build the testsuite by setting BUILD_ILM_API_TESTS option. Example: cmake -DBUILD_ILM_API_TESTS 2. After starting up Weston run the testsuite. - Example: <your installation path>/bin/ivi-layermanagement-api-test + Syntax: [wayland_display_to_connect_to] <your installation path>/bin/ivi-layermanagement-api-test + Example: WAYLAND_DISPLAY=wayland-1 $HOME/bin/ivi-layermanagement-api-test diff --git a/ivi-id-agent-modules/ivi-id-agent/CMakeLists.txt b/ivi-id-agent-modules/ivi-id-agent/CMakeLists.txt index ff47808..d5834f3 100644 --- a/ivi-id-agent-modules/ivi-id-agent/CMakeLists.txt +++ b/ivi-id-agent-modules/ivi-id-agent/CMakeLists.txt @@ -39,6 +39,7 @@ include_directories( link_directories( ${WAYLAND_SERVER_LIBRARY_DIRS} ${PIXMAN_LIBRARY_DIRS} + ${LIBWESTON_DESKTOP_LIBRARY_DIRS} ) diff --git a/ivi-id-agent-modules/ivi-id-agent/src/ivi-id-agent.c b/ivi-id-agent-modules/ivi-id-agent/src/ivi-id-agent.c index b80e2a4..0ec5943 100644 --- a/ivi-id-agent-modules/ivi-id-agent/src/ivi-id-agent.c +++ b/ivi-id-agent-modules/ivi-id-agent/src/ivi-id-agent.c @@ -365,8 +365,10 @@ ivi_failed: static int32_t deinit(struct ivi_id_agent *ida) { - struct db_elem *db_elem; - wl_list_for_each(db_elem, &ida->app_list, link) { + struct db_elem *db_elem, *dl_elem_next; + wl_list_for_each_safe(db_elem, dl_elem_next, &ida->app_list, link) { + wl_list_remove(&db_elem->link); + free(db_elem->cfg_app_id); free(db_elem->cfg_title); free(db_elem); diff --git a/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c b/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c index 257a1dc..826ee47 100644 --- a/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c +++ b/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c @@ -25,7 +25,7 @@ #include <string.h> #include <weston.h> -#include <weston/ivi-layout-export.h> +#include <ivi-layout-export.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -917,18 +917,6 @@ destroy_seat(struct seat_ctx *ctx_seat) { struct ivisurface *surf; struct wl_resource *resource; - if (ctx_seat->keyboard_grab.keyboard) { - keyboard_grab_cancel(&ctx_seat->keyboard_grab); - weston_keyboard_end_grab(ctx_seat->keyboard_grab.keyboard); - } - if (ctx_seat->pointer_grab.pointer) { - pointer_grab_cancel(&ctx_seat->pointer_grab); - weston_pointer_end_grab(ctx_seat->pointer_grab.pointer); - } - if (ctx_seat->touch_grab.touch) { - touch_grab_cancel(&ctx_seat->touch_grab); - weston_touch_end_grab(ctx_seat->touch_grab.touch); - } /* Remove seat acceptance from surfaces which have input acceptance from * this seat */ @@ -1071,17 +1059,19 @@ setup_input_focus(struct input_context *ctx, uint32_t surface, if (NULL != surf) { wl_list_for_each(st_focus, &surf->accepted_seat_list, link) { ctx_seat = st_focus->seat_ctx; - if (device & ILM_INPUT_DEVICE_POINTER) { - input_ctrl_ptr_set_focus_surf(ctx_seat, surf, enabled); - } - if (device & ILM_INPUT_DEVICE_KEYBOARD) { - input_ctrl_kbd_set_focus_surf(ctx_seat, surf, enabled); - } - if (device & ILM_INPUT_DEVICE_TOUCH) { - /*Touch focus cannot be forced to a particular surface. - * Preserve the old behaviour by sending it to controller. - * TODO: Should we just remove focus setting for touch?*/ - send_input_focus(ctx, surf, device, enabled); + if (ctx_seat != NULL) { + if (device & ILM_INPUT_DEVICE_POINTER) { + input_ctrl_ptr_set_focus_surf(ctx_seat, surf, enabled); + } + if (device & ILM_INPUT_DEVICE_KEYBOARD) { + input_ctrl_kbd_set_focus_surf(ctx_seat, surf, enabled); + } + if (device & ILM_INPUT_DEVICE_TOUCH) { + /*Touch focus cannot be forced to a particular surface. + * Preserve the old behaviour by sending it to controller. + * TODO: Should we just remove focus setting for touch?*/ + send_input_focus(ctx, surf, device, enabled); + } } } } diff --git a/ivi-layermanagement-api/ilmClient/include/ilm_client_platform.h b/ivi-layermanagement-api/ilmClient/include/ilm_client_platform.h index 1fb10af..f281c3e 100644 --- a/ivi-layermanagement-api/ilmClient/include/ilm_client_platform.h +++ b/ivi-layermanagement-api/ilmClient/include/ilm_client_platform.h @@ -35,7 +35,7 @@ typedef struct _ILM_CLIENT_PLATFORM_FUNC ilmErrorTypes (*destroy)(); } ILM_CLIENT_PLATFORM_FUNC; -ILM_CLIENT_PLATFORM_FUNC gIlmClientPlatformFunc; +extern ILM_CLIENT_PLATFORM_FUNC gIlmClientPlatformFunc; void init_ilmClientPlatformTable(); diff --git a/ivi-layermanagement-api/ilmClient/src/ilm_client_wayland_platform.c b/ivi-layermanagement-api/ilmClient/src/ilm_client_wayland_platform.c index 55b1621..12052f8 100644 --- a/ivi-layermanagement-api/ilmClient/src/ilm_client_wayland_platform.c +++ b/ivi-layermanagement-api/ilmClient/src/ilm_client_wayland_platform.c @@ -27,6 +27,8 @@ #include "wayland-util.h" #include "ivi-application-client-protocol.h" +ILM_CLIENT_PLATFORM_FUNC gIlmClientPlatformFunc; + static ilmErrorTypes wayland_surfaceCreate(t_ilm_nativehandle nativehandle, t_ilm_int width, t_ilm_int height, ilmPixelFormat pixelFormat, diff --git a/ivi-layermanagement-api/ilmCommon/include/ilm_common.h b/ivi-layermanagement-api/ilmCommon/include/ilm_common.h index fa86824..61e240a 100644 --- a/ivi-layermanagement-api/ilmCommon/include/ilm_common.h +++ b/ivi-layermanagement-api/ilmCommon/include/ilm_common.h @@ -65,6 +65,19 @@ t_ilm_bool ilm_isInitialized(void); ilmErrorTypes ilm_commitChanges(void); /** + * \brief register for notification on an event of ilm shutdown + * \ingroup ilmCommon + * \param[in] callback pointer to function to be called for notification + callback function is defined as: + void cb(t_ilm_shutdown_error_type error_type, int errornum, void *user_data) + * \param[in] user_data pointer to data which will be passed to a notification callback + * \return ILM_SUCCESS if the method call was successful + * \return ILM_FAILED if the client can not call the method on the service. + */ +ilmErrorTypes ilm_registerShutdownNotification(shutdownNotificationFunc callback, + void *user_data); + +/** * \brief Destroys the IVI LayerManagement Client. * \ingroup ilmCommon * \return ILM_SUCCESS if the method call was successful diff --git a/ivi-layermanagement-api/ilmCommon/include/ilm_common_platform.h b/ivi-layermanagement-api/ilmCommon/include/ilm_common_platform.h index 4e7b55e..ec49467 100644 --- a/ivi-layermanagement-api/ilmCommon/include/ilm_common_platform.h +++ b/ivi-layermanagement-api/ilmCommon/include/ilm_common_platform.h @@ -32,7 +32,7 @@ typedef struct _ILM_COMMON_PLATFORM_FUNC ilmErrorTypes (*destroy)(); } ILM_COMMON_PLATFORM_FUNC; -ILM_COMMON_PLATFORM_FUNC gIlmCommonPlatformFunc; +extern ILM_COMMON_PLATFORM_FUNC gIlmCommonPlatformFunc; void init_ilmCommonPlatformTable(); diff --git a/ivi-layermanagement-api/ilmCommon/include/ilm_types.h b/ivi-layermanagement-api/ilmCommon/include/ilm_types.h index a88f2b0..98a8e62 100644 --- a/ivi-layermanagement-api/ilmCommon/include/ilm_types.h +++ b/ivi-layermanagement-api/ilmCommon/include/ilm_types.h @@ -249,6 +249,16 @@ typedef enum } t_ilm_notification_mask; /** + * enum representing types of possible unrecoverable errors that could lead to ilm shutdown. + */ +typedef enum +{ + ILM_ERROR_WAYLAND = 1, /*!< ErrorCode if Wayland API returns an error */ + ILM_ERROR_POLL = 2 /*!< ErrorCode if Poll returns an error */ +}t_ilm_shutdown_error_type; + + +/** * Typedef for notification callback on property changes of a layer */ typedef void(*layerNotificationFunc)(t_ilm_layer layer, @@ -270,4 +280,11 @@ typedef void(*notificationFunc)(ilmObjectType object, t_ilm_bool created, void* user_data); +/** + * Typedef for notification callback on ilm shutdown due to unrecoverable + * errors + */ +typedef void(*shutdownNotificationFunc)(t_ilm_shutdown_error_type error_type, + int errornum, + void* user_data); #endif /* _ILM_TYPES_H_*/ diff --git a/ivi-layermanagement-api/ilmCommon/src/ilm_common.c b/ivi-layermanagement-api/ilmCommon/src/ilm_common.c index f9940d8..63342b9 100644 --- a/ivi-layermanagement-api/ilmCommon/src/ilm_common.c +++ b/ivi-layermanagement-api/ilmCommon/src/ilm_common.c @@ -26,6 +26,9 @@ #include "ilm_types.h" ILM_EXPORT ilmErrorTypes ilmControl_init(t_ilm_nativedisplay); +ILM_EXPORT ilmErrorTypes ilmControl_registerShutdownNotification( + shutdownNotificationFunc callback, + void *user_data); ILM_EXPORT void ilmControl_destroy(void); static pthread_mutex_t g_initialize_lock = PTHREAD_MUTEX_INITIALIZER; @@ -91,7 +94,16 @@ ilm_initWithNativedisplay(t_ilm_nativedisplay nativedisplay) ILM_EXPORT t_ilm_bool ilm_isInitialized(void) { - return gIlmCommonPlatformFunc.isInitialized(); + if(gIlmCommonPlatformFunc.isInitialized) + return gIlmCommonPlatformFunc.isInitialized(); + + return ILM_FALSE; +} + +ILM_EXPORT ilmErrorTypes +ilm_registerShutdownNotification(shutdownNotificationFunc callback, void *user_data) +{ + return ilmControl_registerShutdownNotification(callback, user_data); } ILM_EXPORT ilmErrorTypes diff --git a/ivi-layermanagement-api/ilmCommon/src/ilm_common_wayland_platform.c b/ivi-layermanagement-api/ilmCommon/src/ilm_common_wayland_platform.c index 7470d0d..eef842d 100644 --- a/ivi-layermanagement-api/ilmCommon/src/ilm_common_wayland_platform.c +++ b/ivi-layermanagement-api/ilmCommon/src/ilm_common_wayland_platform.c @@ -32,6 +32,8 @@ static t_ilm_nativedisplay wayland_getNativedisplay(void); static t_ilm_bool wayland_isInitialized(void); static ilmErrorTypes wayland_destroy(void); +ILM_COMMON_PLATFORM_FUNC gIlmCommonPlatformFunc; + void init_ilmCommonPlatformTable(void) { gIlmCommonPlatformFunc.init = wayland_init; diff --git a/ivi-layermanagement-api/ilmControl/CMakeLists.txt b/ivi-layermanagement-api/ilmControl/CMakeLists.txt index 4265ef9..b0e6b22 100644 --- a/ivi-layermanagement-api/ilmControl/CMakeLists.txt +++ b/ivi-layermanagement-api/ilmControl/CMakeLists.txt @@ -65,7 +65,7 @@ add_custom_command( include_directories( include ${ILM_COMMON_INCLUDE_DIRS} - ${WAYLAND_CLIENT_INCLUDE_DIR} + ${WAYLAND_CLIENT_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ) @@ -76,6 +76,7 @@ link_directories( add_library(${PROJECT_NAME} SHARED src/ilm_control_wayland_platform.c src/bitmap.c + src/writepng.c ivi-wm-client-protocol.h ivi-wm-protocol.c ivi-input-client-protocol.h @@ -90,6 +91,7 @@ set(LIBS ${LIBS} rt dl + png ${CMAKE_THREAD_LIBS_INIT} ${WAYLAND_CLIENT_LIBRARIES} ) diff --git a/ivi-layermanagement-api/ilmControl/include/ilm_control_platform.h b/ivi-layermanagement-api/ilmControl/include/ilm_control_platform.h index 4a92c9e..db672cc 100644 --- a/ivi-layermanagement-api/ilmControl/include/ilm_control_platform.h +++ b/ivi-layermanagement-api/ilmControl/include/ilm_control_platform.h @@ -58,6 +58,9 @@ struct ilm_control_context { pthread_mutex_t mutex; int shutdown_fd; uint32_t internal_id_surface; + + shutdownNotificationFunc notification; + void *notification_user_data; }; struct seat_context { diff --git a/ivi-layermanagement-api/ilmControl/src/bitmap.c b/ivi-layermanagement-api/ilmControl/src/bitmap.c index 2c7fdb5..79d2a5d 100644 --- a/ivi-layermanagement-api/ilmControl/src/bitmap.c +++ b/ivi-layermanagement-api/ilmControl/src/bitmap.c @@ -21,6 +21,11 @@ */ #include "bitmap.h" #include <stdio.h> +#include <stdlib.h> +#include <stdlib.h> +#include <stdbool.h> +#include <arpa/inet.h> +#include "ivi-wm-client-protocol.h" struct __attribute__ ((__packed__)) BITMAPFILEHEADER { char bfType[2]; @@ -49,22 +54,22 @@ create_file_header(struct BITMAPFILEHEADER *file_header, int32_t image_size) { file_header->bfType[0] = 'B'; file_header->bfType[1] = 'M'; - file_header->bfSize = sizeof(struct BITMAPFILEHEADER) - + sizeof(struct BITMAPINFOHEADER) - + image_size; - file_header->bfOffBits = sizeof(struct BITMAPFILEHEADER) - + sizeof(struct BITMAPINFOHEADER); + file_header->bfSize = htole32(sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER) + + image_size); + file_header->bfOffBits = htole32(sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER)); } static void create_info_header(struct BITMAPINFOHEADER *info_header, int32_t image_size, int32_t width, int32_t height, int16_t bpp) { - info_header->biSize = sizeof(struct BITMAPINFOHEADER); - info_header->biWidth = width; - info_header->biHeight = height; - info_header->biPlanes = 1; - info_header->biBitCount = bpp; - info_header->biSizeImage = image_size; + info_header->biSize = htole32(sizeof(struct BITMAPINFOHEADER)); + info_header->biWidth = htole32(width); + info_header->biHeight = htole32(height); + info_header->biPlanes = htole16(1); + info_header->biBitCount = htole16(bpp); + info_header->biSizeImage = htole32(image_size); } static int @@ -89,19 +94,87 @@ write_bitmap(const char *filename, int save_as_bitmap(const char *filename, const char *buffer, - int32_t image_size, int32_t width, int32_t height, - int16_t bpp) + uint32_t format) { + int32_t image_stride = 0; + int32_t image_size = 0; + char *image_buffer = NULL; + int32_t row = 0; + int32_t col = 0; + int32_t image_offset = 0; + int32_t offset = 0; + int32_t i = 0; + int32_t j = 0; + int bytes_per_pixel; + bool flip_order; + bool has_alpha; + if ((filename == NULL) || (buffer == NULL)) { return -1; } + switch (format) { + case WL_SHM_FORMAT_ARGB8888: + flip_order = true; + has_alpha = true; + break; + case WL_SHM_FORMAT_XRGB8888: + flip_order = true; + has_alpha = false; + break; + case WL_SHM_FORMAT_ABGR8888: + flip_order = false; + has_alpha = true; + break; + case WL_SHM_FORMAT_XBGR8888: + flip_order = false; + has_alpha = false; + break; + default: + fprintf(stderr, "unsupported pixelformat 0x%x\n", format); + return -1; + } + + bytes_per_pixel = has_alpha ? 4 : 3; + image_stride = (((width * bytes_per_pixel) + 3) & ~3); + image_size = image_stride * height; + + image_buffer = malloc(image_size); + if (image_buffer == NULL) { + fprintf(stderr, "failed to allocate %d bytes for image buffer: %m\n", + image_size); + return -1; + } + + // Store the image in image_buffer in the follwing order B, G, R, [A](B at the lowest address) + for (row = 0; row < height; ++row) { + for (col = 0; col < width; ++col) { + offset = (height - row - 1) * width + col; + uint32_t pixel = htonl(((uint32_t*)buffer)[offset]); + char * pixel_p = (char*) &pixel; + image_offset = row * image_stride + col * bytes_per_pixel; + for (i = 0; i < 3; ++i) { + j = flip_order ? 2 - i : i; + image_buffer[image_offset + i] = pixel_p[1 + j]; + } + if (has_alpha) { + image_buffer[image_offset + 3] = pixel_p[0]; + } + } + } + struct BITMAPFILEHEADER file_header = {}; struct BITMAPINFOHEADER info_header = {}; create_file_header(&file_header, image_size); - create_info_header(&info_header, image_size, width, height, bpp); - return write_bitmap(filename, &file_header, &info_header, buffer); + create_info_header(&info_header, image_size, width, height, bytes_per_pixel * 8); + if (write_bitmap(filename, &file_header, &info_header, image_buffer) != 0) { + free(image_buffer); + return -1; + } + + free(image_buffer); + return 0; } diff --git a/ivi-layermanagement-api/ilmControl/src/bitmap.h b/ivi-layermanagement-api/ilmControl/src/bitmap.h index 3cef52d..4b8520c 100644 --- a/ivi-layermanagement-api/ilmControl/src/bitmap.h +++ b/ivi-layermanagement-api/ilmControl/src/bitmap.h @@ -26,10 +26,9 @@ int save_as_bitmap(const char *filename, const char *buffer, - int32_t image_size, int32_t width, int32_t height, - int16_t bpp + uint32_t format ); #endif /* IVICONTROLLER_BITMAP_H_*/ diff --git a/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c b/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c index a912e50..f1e5404 100644 --- a/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c +++ b/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c @@ -30,6 +30,7 @@ #include <sys/mman.h> #include <sys/eventfd.h> +#include "writepng.h" #include "bitmap.h" #include "ilm_common.h" #include "ilm_control_platform.h" @@ -1083,6 +1084,28 @@ static void send_shutdown_event(struct ilm_control_context *ctx) ; } +ILM_EXPORT ilmErrorTypes +ilmControl_registerShutdownNotification(shutdownNotificationFunc callback, void *user_data) +{ + ilmErrorTypes returnValue = ILM_FAILED; + struct ilm_control_context *ctx = sync_and_acquire_instance(); + + if (!callback) + { + fprintf(stderr, "[Error] shutdownNotificationFunc is invalid\n"); + goto error; + } + + ctx->notification = callback; + ctx->notification_user_data = user_data; + + returnValue = ILM_SUCCESS; + +error: + release_instance(); + return returnValue; +} + ILM_EXPORT void ilmControl_destroy(void) { @@ -1127,6 +1150,8 @@ ilmControl_init(t_ilm_nativedisplay nativedisplay) } ctx->shutdown_fd = -1; + ctx->notification = NULL; + ctx->notification_user_data = NULL; ctx->wl.display = (struct wl_display*)nativedisplay; @@ -1167,6 +1192,34 @@ ilmControl_init(t_ilm_nativedisplay nativedisplay) return ILM_SUCCESS; } +static void +handle_shutdown(struct ilm_control_context *ctx, + t_ilm_shutdown_error_type error_type) +{ + struct wayland_context *wl_ctx = &ctx->wl; + struct wl_display *display = wl_ctx->display; + int errornum; + + switch (error_type) + { + case ILM_ERROR_WAYLAND: + errornum = wl_display_get_error(display); + break; + case ILM_ERROR_POLL: + default: + errornum = errno; + } + + fprintf(stderr, "[Error] ilm services shutdown due to error %s\n", + strerror(errornum)); + + if (!ctx->notification) + return; + + ctx->notification(error_type, errornum, ctx->notification_user_data); +} + + static void* control_thread(void *p_ret) { @@ -1189,6 +1242,7 @@ control_thread(void *p_ret) if (wl_display_flush(display) == -1) { + handle_shutdown(ctx, ILM_ERROR_WAYLAND); break; } @@ -1208,11 +1262,15 @@ control_thread(void *p_ret) if (ret == -1) { + handle_shutdown(ctx, ILM_ERROR_WAYLAND); break; } } else { + if (pollret == -1) + handle_shutdown(ctx, ILM_ERROR_POLL); + wl_display_cancel_read(display); if (pollret == -1 || (pfd[1].revents & POLLIN)) @@ -2061,43 +2119,16 @@ static void screenshot_done(void *data, struct ivi_screenshot *ivi_screenshot, { struct screenshot_context *ctx_scrshot = data; char *buffer; - int32_t image_stride = 0; - int32_t image_size = 0; - char *image_buffer = NULL; - int32_t row = 0; - int32_t col = 0; - int32_t image_offset = 0; - int32_t offset = 0; - int32_t i = 0; - int32_t j = 0; size_t size = stride * height; - int bytes_per_pixel; - bool flip_order; - bool has_alpha; const char *filename = ctx_scrshot->filename; + char *filename_ext = NULL; ctx_scrshot->filename = NULL; ivi_screenshot_destroy(ivi_screenshot); - switch (format) { - case WL_SHM_FORMAT_ARGB8888: - flip_order = false; - has_alpha = true; - break; - case WL_SHM_FORMAT_XRGB8888: - flip_order = false; - has_alpha = false; - break; - case WL_SHM_FORMAT_ABGR8888: - flip_order = true; - has_alpha = true; - break; - case WL_SHM_FORMAT_XBGR8888: - flip_order = true; - has_alpha = false; - break; - default: - fprintf(stderr, "unsupported pixelformat 0x%x\n", format); + if (filename == NULL) { + ctx_scrshot->result = ILM_FAILED; + fprintf(stderr, "screenshot file name not provided: %m\n"); return; } @@ -2105,45 +2136,34 @@ static void screenshot_done(void *data, struct ivi_screenshot *ivi_screenshot, close(fd); if (buffer == MAP_FAILED) { + ctx_scrshot->result = ILM_FAILED; fprintf(stderr, "failed to mmap screenshot file: %m\n"); return; } - bytes_per_pixel = has_alpha ? 4 : 3; - image_stride = (((width * bytes_per_pixel) + 3) & ~3); - image_size = image_stride * height; - - image_buffer = malloc(image_size); - if (image_buffer == NULL) { - fprintf(stderr, "failed to allocate %d bytes for image buffer: %m\n", - image_size); - munmap(buffer, size); - return; - } + if ((filename_ext = strstr(filename, ".png")) && (strlen(filename_ext) == 4)) { + if (save_as_png(filename, (const char *)buffer, + width, height, format) == 0) { + ctx_scrshot->result = ILM_SUCCESS; + } else { + ctx_scrshot->result = ILM_FAILED; + fprintf(stderr, "failed to write screenshot as png file: %m\n"); + } + } else { + if (!((filename_ext = strstr(filename, ".bmp")) && (strlen(filename_ext) == 4))) { + fprintf(stderr, "trying to write screenshot as bmp file, although file extension does not match: %m\n"); + } - for (row = 0; row < height; ++row) { - for (col = 0; col < width; ++col) { - offset = (height - row - 1) * width + col; - image_offset = row * image_stride + col * bytes_per_pixel; - for (i = 0; i < 3; ++i) { - j = flip_order ? 2 - i : i; - image_buffer[image_offset + i] = buffer[offset * 4 + j]; - } - if (has_alpha) - image_buffer[image_offset + 3] = buffer[offset * 4 + 3]; + if (save_as_bitmap(filename, (const char *)buffer, + width, height, format) == 0) { + ctx_scrshot->result = ILM_SUCCESS; + } else { + ctx_scrshot->result = ILM_FAILED; + fprintf(stderr, "failed to write screenshot as bmp file: %m\n"); } } munmap(buffer, size); - - if (save_as_bitmap(filename, (const char *)image_buffer, - image_size, width, height, bytes_per_pixel * 8) == 0) { - ctx_scrshot->result = ILM_SUCCESS; - } else { - fprintf(stderr, "failed to write screenshot file: %m\n"); - } - - free(image_buffer); } static void screenshot_error(void *data, struct ivi_screenshot *ivi_screenshot, diff --git a/ivi-layermanagement-api/ilmControl/src/writepng.c b/ivi-layermanagement-api/ilmControl/src/writepng.c new file mode 100644 index 0000000..bf712b5 --- /dev/null +++ b/ivi-layermanagement-api/ilmControl/src/writepng.c @@ -0,0 +1,218 @@ +/*************************************************************************** + * + * Copyright (C) 2020 Advanced Driver Information Technology Joint Venture GmbH + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <arpa/inet.h> +#include "png.h" +#include "ivi-wm-client-protocol.h" +#include "writepng.h" + +typedef struct _image_info { + png_structp png_ptr; + png_infop info_ptr; + jmp_buf jmpbuf; + FILE *outfile; +} image_info; + + +static void +writepng_error_handler(png_structp png_ptr, + png_const_charp msg) +{ + fprintf(stderr, "writepng libpng error: %s\n", msg); +} + +static int +create_png_header(image_info *info, + int32_t width, + int32_t height, + uint32_t format) +{ + int color_type = 0; + int sample_depth = 8; + + info->info_ptr = png_create_info_struct(info->png_ptr); + if (!info->info_ptr) { + fprintf(stderr, "png_create_info_struct: failed, out of memory\n"); + png_destroy_write_struct(&info->png_ptr, NULL); + return -1; + } + + if (setjmp(info->jmpbuf)) { + fprintf(stderr, "setjmp: failed\n"); + png_destroy_write_struct(&info->png_ptr, &info->info_ptr); + return -1; + } + + png_init_io(info->png_ptr, info->outfile); + + png_set_compression_level(info->png_ptr, PNG_Z_DEFAULT_COMPRESSION); + + switch (format) { + case WL_SHM_FORMAT_ARGB8888: + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + png_set_swap_alpha(info->png_ptr); + break; + case WL_SHM_FORMAT_XRGB8888: + color_type = PNG_COLOR_TYPE_RGB; + break; + case WL_SHM_FORMAT_ABGR8888: + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + png_set_bgr(info->png_ptr); + png_set_swap_alpha(info->png_ptr); + break; + case WL_SHM_FORMAT_XBGR8888: + color_type = PNG_COLOR_TYPE_RGB; + png_set_bgr(info->png_ptr); + break; + default: + fprintf(stderr, "unsupported pixelformat 0x%x\n", format); + return -1; + } + + png_set_IHDR(info->png_ptr, info->info_ptr, width, height, + sample_depth, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_write_info(info->png_ptr, info->info_ptr); + + return 0; +} + +static int +write_png_file(image_info *info, + const char *buffer, + int32_t width, + int32_t height, + uint32_t format, + int bytes_per_pixel) +{ + info->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, + writepng_error_handler, NULL); + if (!info->png_ptr) { + fprintf(stderr, "png_create_write_struct: failed, out of memory\n"); + return -1; + } + + if (create_png_header(info, width, height, format) != 0) { + return -1; + } + + for(int j = 0; j < height ; ++j) { + png_const_bytep pointer = (png_const_bytep)buffer; + pointer += j * width * bytes_per_pixel; + + if (setjmp(info->jmpbuf)) { + fprintf(stderr, "setjmp: failed, j=%d\n", j); + png_destroy_write_struct(&info->png_ptr, &info->info_ptr); + info->png_ptr = NULL; + info->info_ptr = NULL; + return -1; + } + + png_write_row(info->png_ptr, pointer); + } + + if (setjmp(info->jmpbuf)) { + fprintf(stderr, "final setjmp failed\n"); + png_destroy_write_struct(&info->png_ptr, &info->info_ptr); + info->png_ptr = NULL; + info->info_ptr = NULL; + return -1; + } + + png_write_end(info->png_ptr, NULL); + + if (info->png_ptr && info->info_ptr) { + png_destroy_write_struct(&info->png_ptr, &info->info_ptr); + } + + return 0; +} + +int +save_as_png(const char *filename, + const char *buffer, + int32_t width, + int32_t height, + uint32_t format) +{ + int32_t image_stride = 0; + int32_t image_size = 0; + char *image_buffer = NULL; + int32_t row = 0; + int32_t col = 0; + int32_t image_offset = 0; + int32_t offset = 0; + int bytes_per_pixel = 0; + bool has_alpha = false; + image_info info; + + if ((filename == NULL) || (buffer == NULL)) { + return -1; + } + + info.outfile = fopen(filename, "wb"); + if (!info.outfile) { + fprintf(stderr, "could not open the file %s\n", filename); + return -1; + } + + switch (format) { + case WL_SHM_FORMAT_ARGB8888: + case WL_SHM_FORMAT_ABGR8888: + has_alpha = true; + break; + default: + has_alpha = false; + break; + } + + bytes_per_pixel = has_alpha ? 4 : 3; + image_stride = (((width * bytes_per_pixel) + 3) & ~3); + image_size = image_stride * height; + + image_buffer = malloc(image_size); + if (image_buffer == NULL) { + fprintf(stderr, "failed to allocate %d bytes for image buffer: %m\n", + image_size); + return -1; + } + + for (row = 0; row < height; ++row) { + for (col = 0; col < width; ++col) { + offset = row * width + col; + uint32_t pixel = htonl(((uint32_t*)buffer)[offset]); + char * pixel_p = (char*) &pixel; + image_offset = row * image_stride + col * bytes_per_pixel; + for (int i=0; i<bytes_per_pixel; ++i){ + image_buffer[image_offset + i] = pixel_p[i + (has_alpha ? 0 : 1)]; + } + } + } + + if (write_png_file(&info, image_buffer, width, height, format, bytes_per_pixel) != 0) { + free(image_buffer); + return -1; + } + + free(image_buffer); + return 0; +} diff --git a/ivi-layermanagement-api/ilmControl/src/writepng.h b/ivi-layermanagement-api/ilmControl/src/writepng.h new file mode 100644 index 0000000..0331a0a --- /dev/null +++ b/ivi-layermanagement-api/ilmControl/src/writepng.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * + * Copyright (C) 2020 Advanced Driver Information Technology Joint Venture GmbH + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +#ifndef IVICONTROLLER_WRITEPNG_H_ +#define IVICONTROLLER_WRITEPNG_H_ + +#include <stdint.h> + +int +save_as_png(const char *filename, + const char *buffer, + int32_t width, + int32_t height, + uint32_t format); + +#endif /* IVICONTROLLER_WRITEPNG_H_ */ diff --git a/ivi-layermanagement-api/ilmInput/CMakeLists.txt b/ivi-layermanagement-api/ilmInput/CMakeLists.txt index b4c794c..f2ed324 100644 --- a/ivi-layermanagement-api/ilmInput/CMakeLists.txt +++ b/ivi-layermanagement-api/ilmInput/CMakeLists.txt @@ -50,7 +50,7 @@ include_directories( include ${CMAKE_CURRENT_BINARY_DIR} ${ILM_CONTROL_INCLUDE_DIRS} - ${WAYLAND_CLIENT_INCLUDE_DIR} + ${WAYLAND_CLIENT_INCLUDE_DIRS} ) link_directories( diff --git a/ivi-layermanagement-api/test/ilm_input_test.cpp b/ivi-layermanagement-api/test/ilm_input_test.cpp index abc392d..032a7e3 100644 --- a/ivi-layermanagement-api/test/ilm_input_test.cpp +++ b/ivi-layermanagement-api/test/ilm_input_test.cpp @@ -125,8 +125,9 @@ TEST_F(IlmInputTest, ilm_input_focus) { for (unsigned int i = 0; i < num_ids; i++) { /* All surfaces now have keyboard focus */ for (unsigned int j = 0; j < surfaceCount; j++) { - if (surfaceIDs[i] == surfaces[j]) + if (surfaceIDs[i] == surfaces[j]) { EXPECT_EQ(bitmasks[i], ILM_INPUT_DEVICE_KEYBOARD); + } } } free(surfaceIDs); @@ -136,9 +137,11 @@ TEST_F(IlmInputTest, ilm_input_focus) { ASSERT_EQ(ILM_SUCCESS, ilm_setInputFocus(&surfaces[0], 1, ILM_INPUT_DEVICE_KEYBOARD, ILM_FALSE)); ASSERT_EQ(ILM_SUCCESS, ilm_getInputFocus(&surfaceIDs, &bitmasks, &num_ids)); /* keyboard focus now removed for surfaces[0] */ - for (unsigned int i = 0; i < num_ids; i++) - if (surfaceIDs[i] == surfaces[0]) + for (unsigned int i = 0; i < num_ids; i++) { + if (surfaceIDs[i] == surfaces[0]) { EXPECT_EQ(bitmasks[i], 0); + } + } free(surfaceIDs); free(bitmasks); @@ -146,9 +149,11 @@ TEST_F(IlmInputTest, ilm_input_focus) { ASSERT_EQ(ILM_SUCCESS, ilm_setInputFocus(&surfaces[1], 1, ILM_INPUT_DEVICE_POINTER, ILM_TRUE)); ASSERT_EQ(ILM_SUCCESS, ilm_getInputFocus(&surfaceIDs, &bitmasks, &num_ids)); /* surfaces[1] now has pointer and keyboard focus */ - for (unsigned int i = 0; i < num_ids; i++) - if (surfaceIDs[i] == surfaces[1]) + for (unsigned int i = 0; i < num_ids; i++) { + if (surfaceIDs[i] == surfaces[1]) { EXPECT_EQ(bitmasks[i], ILM_INPUT_DEVICE_POINTER | ILM_INPUT_DEVICE_KEYBOARD); + } + } free(surfaceIDs); free(bitmasks); @@ -156,9 +161,11 @@ TEST_F(IlmInputTest, ilm_input_focus) { ASSERT_EQ(ILM_SUCCESS, ilm_setInputFocus(&surfaces[2], 1, ILM_INPUT_DEVICE_TOUCH, ILM_TRUE)); ASSERT_EQ(ILM_SUCCESS, ilm_getInputFocus(&surfaceIDs, &bitmasks, &num_ids)); /* surfaces[2] now has keyboard and touch focus */ - for (unsigned int i = 0; i < num_ids; i++) - if (surfaceIDs[i] == surfaces[2]) + for (unsigned int i = 0; i < num_ids; i++) { + if (surfaceIDs[i] == surfaces[2]) { EXPECT_EQ(bitmasks[i], ILM_INPUT_DEVICE_KEYBOARD | ILM_INPUT_DEVICE_TOUCH); + } + } free(surfaceIDs); free(bitmasks); } diff --git a/ivi-layermanagement-examples/EGLWLInputEventExample/CMakeLists.txt b/ivi-layermanagement-examples/EGLWLInputEventExample/CMakeLists.txt index 76d8def..e8596e8 100644 --- a/ivi-layermanagement-examples/EGLWLInputEventExample/CMakeLists.txt +++ b/ivi-layermanagement-examples/EGLWLInputEventExample/CMakeLists.txt @@ -48,11 +48,11 @@ add_custom_command( ) include_directories( - ${GLESv2_INCLUDE_DIR} - ${EGL_INCLUDE_DIR} - ${WAYLAND_CLIENT_INCLUDE_DIR} - ${WAYLAND_CURSOR_INCLUDE_DIR} - ${FFI_INCLUDE_DIR} + ${GLESv2_INCLUDE_DIRS} + ${EGL_INCLUDE_DIRS} + ${WAYLAND_CLIENT_INCLUDE_DIRS} + ${WAYLAND_CURSOR_INCLUDE_DIRS} + ${FFI_INCLUDE_DIRS} "include" ${CMAKE_CURRENT_BINARY_DIR} ) diff --git a/ivi-layermanagement-examples/EGLWLInputEventExample/src/WLContext.cpp b/ivi-layermanagement-examples/EGLWLInputEventExample/src/WLContext.cpp index ade58f0..edcbaff 100644 --- a/ivi-layermanagement-examples/EGLWLInputEventExample/src/WLContext.cpp +++ b/ivi-layermanagement-examples/EGLWLInputEventExample/src/WLContext.cpp @@ -64,6 +64,7 @@ WLContext::~WLContext() * The following correspondences between file names and cursors was copied * from: https://bugs.kde.org/attachment.cgi?id=67313 */ +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) static const char *left_ptrs[] = { "left_ptr", @@ -84,14 +85,13 @@ create_cursors(WLContext* wlContext) fprintf(stderr, "could not load default theme\n"); return; } - wlContext->SetWLCursor((wl_cursor*) malloc(sizeof(wl_cursor))); - for (j = 0; !cursor && j < 4; ++j) + for (j = 0; !cursor && j < ARRAY_SIZE(left_ptrs); ++j) cursor = wl_cursor_theme_get_cursor(wlContext->GetWLCursorTheme(), left_ptrs[j]); if (!cursor) - fprintf(stderr, "could not load cursor '%s'\n", left_ptrs[j]); + fprintf(stderr, "could not load any cursor\n"); wlContext->SetWLCursor(cursor); } @@ -170,11 +170,10 @@ WLContext::SeatHandleCapabilities(void* data, struct wl_seat* seat, uint32_t cap context->ctx->SetPointerSurface(NULL); } - if (context->ctx->GetWLCursorTheme()) + if (context->ctx->GetWLCursorTheme()){ wl_cursor_theme_destroy(context->ctx->GetWLCursorTheme()); - - if (context->ctx->GetWLCursor()) - free(context->ctx->GetWLCursor()); + context->ctx->SetWLCursor(NULL); + } } if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !context->wlKeyboard){ @@ -235,11 +234,11 @@ WLContext::DestroyWLContext() m_pointerSurface = NULL; } - if (m_wlCursorTheme) + if (m_wlCursorTheme){ wl_cursor_theme_destroy(m_wlCursorTheme); - - if (m_wlCursor) - free(m_wlCursor); + m_wlCursorTheme = NULL; + m_wlCursor = NULL; + } wl_registry_destroy(m_wlRegistry); wl_display_flush(m_wlDisplay); diff --git a/ivi-layermanagement-examples/EGLWLMockNavigation/src/TextureLoader.cpp b/ivi-layermanagement-examples/EGLWLMockNavigation/src/TextureLoader.cpp index 30c170f..77dd5fd 100644 --- a/ivi-layermanagement-examples/EGLWLMockNavigation/src/TextureLoader.cpp +++ b/ivi-layermanagement-examples/EGLWLMockNavigation/src/TextureLoader.cpp @@ -67,7 +67,8 @@ bool TextureLoader::loadBMP(const char * imagePath) { } data = new unsigned char [imageSize]; - fread(data,1,imageSize,file); + if(fread(data,1,imageSize,file) != imageSize) + cout << "Reading error : mismatch in imageSize and amount of data read" << endl; fclose(file); if (pixelSizeBits == 32) { diff --git a/ivi-layermanagement-examples/LayerManagerControl/CMakeLists.txt b/ivi-layermanagement-examples/LayerManagerControl/CMakeLists.txt index aeb3269..5a01682 100644 --- a/ivi-layermanagement-examples/LayerManagerControl/CMakeLists.txt +++ b/ivi-layermanagement-examples/LayerManagerControl/CMakeLists.txt @@ -24,7 +24,7 @@ include_directories( "${CMAKE_SOURCE_DIR}/ivi-layermanagement-api/ilmCommon/include" "${CMAKE_SOURCE_DIR}/ivi-layermanagement-api/ilmControl/include" "${CMAKE_SOURCE_DIR}/ivi-layermanagement-api/ilmInput/include" - ${WAYLAND_CLIENT_INCLUDE_DIR} + ${WAYLAND_CLIENT_INCLUDE_DIRS} ) link_directories( diff --git a/ivi-layermanagement-examples/layer-add-surfaces/CMakeLists.txt b/ivi-layermanagement-examples/layer-add-surfaces/CMakeLists.txt index f846663..78db1af 100644 --- a/ivi-layermanagement-examples/layer-add-surfaces/CMakeLists.txt +++ b/ivi-layermanagement-examples/layer-add-surfaces/CMakeLists.txt @@ -24,7 +24,7 @@ include_directories( "${CMAKE_SOURCE_DIR}/ivi-layermanagement-api/ilmCommon/include" "${CMAKE_SOURCE_DIR}/ivi-layermanagement-api/ilmClient/include" "${CMAKE_SOURCE_DIR}/ivi-layermanagement-api/ilmControl/include" - ${WAYLAND_CLIENT_INCLUDE_DIR} + ${WAYLAND_CLIENT_INCLUDE_DIRS} ) link_directories( diff --git a/ivi-layermanagement-examples/layer-add-surfaces/src/layer-add-surfaces.c b/ivi-layermanagement-examples/layer-add-surfaces/src/layer-add-surfaces.c index 5a31fa3..a271da2 100644 --- a/ivi-layermanagement-examples/layer-add-surfaces/src/layer-add-surfaces.c +++ b/ivi-layermanagement-examples/layer-add-surfaces/src/layer-add-surfaces.c @@ -96,6 +96,35 @@ static void callbackFunction(ilmObjectType object, t_ilm_uint id, t_ilm_bool cre } } +static void shutdownCallbackFunction(t_ilm_shutdown_error_type error_type, + int errornum, + void *user_data) +{ + (void) user_data; + + switch (error_type) { + case ILM_ERROR_WAYLAND: + { + printf("layer-add-surfaces: exit, ilm shutdown due to wayland error: %s\n", + strerror(errornum)); + break; + } + case ILM_ERROR_POLL: + { + printf("layer-add-surfaces: exit, ilm shutdown due to poll error: %s\n", + strerror(errornum)); + break; + } + default: + { + printf("layer-add-surfaces: exit, ilm shutdown due to unknown reason: %s\n", + strerror(errornum)); + } + } + + exit(1); +} + /* Choose the display with the largest resolution.*/ static t_ilm_uint choose_screen(void) { @@ -235,6 +264,8 @@ int main (int argc, char *argv[]) return -1; } + ilm_registerShutdownNotification(shutdownCallbackFunction, NULL); + screen_ID = choose_screen(); ilm_layerCreateWithDimension(&layer, screenWidth, screenHeight); printf("layer-add-surfaces: layer (%d) destination region: x:0 y:0 w:%u h:%u\n", layer, screenWidth, screenHeight); diff --git a/ivi-layermanagement-examples/multi-touch-viewer/CMakeLists.txt b/ivi-layermanagement-examples/multi-touch-viewer/CMakeLists.txt index b9036bf..2d0acac 100644 --- a/ivi-layermanagement-examples/multi-touch-viewer/CMakeLists.txt +++ b/ivi-layermanagement-examples/multi-touch-viewer/CMakeLists.txt @@ -56,7 +56,7 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${GLESv2_INCLUDE_DIRS} ${EGL_INCLUDE_DIRS} - ${WAYLAND_CLIENT_INCLUDE_DIR} + ${WAYLAND_CLIENT_INCLUDE_DIRS} ) link_directories( diff --git a/ivi-layermanagement-examples/multi-touch-viewer/include/window.h b/ivi-layermanagement-examples/multi-touch-viewer/include/window.h index 40e2925..d81dda6 100644 --- a/ivi-layermanagement-examples/multi-touch-viewer/include/window.h +++ b/ivi-layermanagement-examples/multi-touch-viewer/include/window.h @@ -46,6 +46,12 @@ struct Task struct wl_list link; }; +enum TypeOfShell +{ + WL_SHELL = 1, + IVI_SHELL = 2 +}; + struct WaylandDisplay { struct Task display_task; @@ -57,6 +63,7 @@ struct WaylandDisplay EGLDisplay egldisplay; EGLConfig eglconfig; EGLContext eglcontext; + enum TypeOfShell shell_type; int running; int epoll_fd; @@ -102,7 +109,7 @@ struct WaylandEglWindow }; struct WaylandDisplay* -CreateDisplay(int argc, char **argv); +CreateDisplay(int argc, char **argv, enum TypeOfShell shell_type); void DestroyDisplay(struct WaylandDisplay *p_display); diff --git a/ivi-layermanagement-examples/multi-touch-viewer/src/multi-touch-viewer.c b/ivi-layermanagement-examples/multi-touch-viewer/src/multi-touch-viewer.c index 6645730..5d97ad4 100644 --- a/ivi-layermanagement-examples/multi-touch-viewer/src/multi-touch-viewer.c +++ b/ivi-layermanagement-examples/multi-touch-viewer/src/multi-touch-viewer.c @@ -30,6 +30,7 @@ #include <sys/stat.h> #include <wayland-client-protocol.h> #include "multi-touch-viewer.h" +#include "getopt.h" #define WINDOW_TITLE "multi_touch_viewer" #define WINDOW_WIDTH 1080 @@ -69,6 +70,7 @@ static const char *gp_frag_shader_text = static struct touch_event_test_params *gp_test_params = NULL; static int g_is_print_log = 0; +static enum TypeOfShell g_shell_type = IVI_SHELL; /******************************************************************************/ @@ -587,7 +589,7 @@ setup_signal() /******************************************************************************/ -int +static int touch_event_test_main(struct touch_event_test_params *p_params) { struct WaylandDisplay *p_display; @@ -595,7 +597,7 @@ touch_event_test_main(struct touch_event_test_params *p_params) setup_signal(); - p_display = CreateDisplay(0, NULL); + p_display = CreateDisplay(0, NULL, g_shell_type); if (NULL == p_display) { LOG_ERROR("Failed to create display\n"); @@ -641,39 +643,65 @@ touch_event_test_main(struct touch_event_test_params *p_params) return 0; } -void +static void usage(int status) { - printf("usage: multi-touch-viewer [OPTION]\n"); - printf(" -p : print received touch point\n"); + fprintf(stderr, " -h, --help display this help and exit.\n" + " -p, --print-log print received touch point.\n" + " -s, --shell-type select the type of shell, default is the ivi_shell:\n" + " - wl_shell: to using the wl_shell.\n" + " - ivi_shell: to using the ivi_shell.\n"); exit(status); } -int -main(int argc, char **argv) +static void +parse_options(int argc, char *argv[]) { - _UNUSED_(argc); - _UNUSED_(argv); - struct touch_event_test_params params; + int opt = -1, option_index = 0; + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "print-log", no_argument, NULL, 'p' }, + { "shell-type", required_argument, NULL, 's' }, + { 0, 0, NULL, 0 } + }; - memset(¶ms, 0x00, sizeof params); + while (1) { + opt = getopt_long(argc, argv, "hps:", options, NULL); - if (argc == 2) - { - if (0 == strcmp(argv[1], "-p")) - { - g_is_print_log = 1; - } - else - { - usage(EXIT_SUCCESS); + if (opt == -1) + break; + + switch (opt) { + case 'h': + usage(0); + break; + case 'p': + g_is_print_log = 1; + break; + case 's': + if (strcmp(optarg, "wl_shell") == 0) + g_shell_type = WL_SHELL; + break; + default: + usage(-1); + break; } } + printf("multi-touch-viewer runs with %s and logging %s\n", + (g_shell_type == WL_SHELL) ? "wl_shell" : "ivi_shell", + (g_is_print_log == 1) ? "enable" : "disable"); +} - gp_test_params = ¶ms; +int +main(int argc, char **argv) +{ + parse_options(argc, argv); - wl_list_init(¶ms.touch_point_list); + struct touch_event_test_params params; + memset(¶ms, 0x00, sizeof params); + gp_test_params = ¶ms; + wl_list_init(¶ms.touch_point_list); log_array_init(¶ms.log_array, 500); return touch_event_test_main(¶ms); diff --git a/ivi-layermanagement-examples/multi-touch-viewer/src/window.c b/ivi-layermanagement-examples/multi-touch-viewer/src/window.c index 41b02a9..abd7788 100644 --- a/ivi-layermanagement-examples/multi-touch-viewer/src/window.c +++ b/ivi-layermanagement-examples/multi-touch-viewer/src/window.c @@ -79,12 +79,14 @@ registry_handle_global(void *p_data, struct wl_registry *p_registry, p_display->p_compositor = wl_registry_bind(p_registry, id, &wl_compositor_interface, 1); } - else if (0 == strcmp(p_interface, "wl_shell")) + else if ((0 == strcmp(p_interface, "wl_shell")) && + (p_display->shell_type == WL_SHELL)) { p_display->p_shell = wl_registry_bind(p_registry, id, &wl_shell_interface, 1); } - else if (0 == strcmp(p_interface, "ivi_application")) + else if ((0 == strcmp(p_interface, "ivi_application")) && + (p_display->shell_type == IVI_SHELL)) { p_display->p_ivi_application = wl_registry_bind(p_registry, id, &ivi_application_interface, 1); @@ -500,7 +502,7 @@ DisplayAcquireWindowSurface(struct WaylandDisplay *p_display, } struct WaylandDisplay * -CreateDisplay(int argc, char **argv) +CreateDisplay(int argc, char **argv, enum TypeOfShell shell_type) { struct WaylandDisplay *p_display; @@ -521,6 +523,7 @@ CreateDisplay(int argc, char **argv) return NULL; } + p_display->shell_type = shell_type; p_display->epoll_fd = os_epoll_create_cloexec(); p_display->display_fd = wl_display_get_fd(p_display->p_display); p_display->display_task.run = handle_display_data; diff --git a/ivi-layermanagement-examples/simple-weston-client/CMakeLists.txt b/ivi-layermanagement-examples/simple-weston-client/CMakeLists.txt index af7e29d..847c9a1 100644 --- a/ivi-layermanagement-examples/simple-weston-client/CMakeLists.txt +++ b/ivi-layermanagement-examples/simple-weston-client/CMakeLists.txt @@ -26,7 +26,7 @@ pkg_check_modules(LIBWESTON_PROTOCOLS libweston-7-protocols QUIET) if(${LIBWESTON_PROTOCOLS_FOUND}) #check for DLT - pkg_check_modules(DLT automotive-dlt REQUIRED) + pkg_check_modules(DLT automotive-dlt QUIET) #import the pkgdatadir from libweston-protocols pkgconfig file execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir libweston-7-protocols @@ -80,10 +80,10 @@ if(${LIBWESTON_PROTOCOLS_FOUND}) endif(${LIBWESTON_PROTOCOLS_FOUND}) include_directories( - ${WAYLAND_CLIENT_INCLUDE_DIR} - ${WAYLAND_CURSOR_INCLUDE_DIR} + ${WAYLAND_CLIENT_INCLUDE_DIRS} + ${WAYLAND_CURSOR_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} - ${DLT_INCLUDE_DIR} + ${DLT_INCLUDE_DIRS} ) link_directories( @@ -118,8 +118,13 @@ add_dependencies(${PROJECT_NAME} ${LIBS}) add_definitions(${DLT_CFLAGS}) +if(${DLT_FOUND}) + add_definitions(-DDLT) +endif(${DLT_FOUND}) + if(${LIBWESTON_PROTOCOLS_FOUND}) add_definitions(-DLIBWESTON_DEBUG_PROTOCOL) + target_link_libraries(${PROJECT_NAME} pthread) endif(${LIBWESTON_PROTOCOLS_FOUND}) target_link_libraries(${PROJECT_NAME} ${LIBS}) diff --git a/ivi-layermanagement-examples/simple-weston-client/src/simple-weston-client.c b/ivi-layermanagement-examples/simple-weston-client/src/simple-weston-client.c index 4093cf2..1434c31 100644 --- a/ivi-layermanagement-examples/simple-weston-client/src/simple-weston-client.c +++ b/ivi-layermanagement-examples/simple-weston-client/src/simple-weston-client.c @@ -36,17 +36,18 @@ #include <ivi-application-client-protocol.h> #ifdef LIBWESTON_DEBUG_PROTOCOL -#include "dlt_common.h" -#include "dlt_user.h" #include "weston-debug-client-protocol.h" +#define MAXSTRLEN 1024 +#endif + +#ifdef DLT +#include "dlt.h" #define WESTON_DLT_APP_DESC "messages from weston debug protocol" #define WESTON_DLT_CONTEXT_DESC "weston debug context" #define WESTON_DLT_APP "WESN" #define WESTON_DLT_CONTEXT "WESC" - -#define MAXSTRLEN 1024 #endif #ifndef MIN @@ -88,6 +89,7 @@ typedef struct _WaylandContext { pthread_t dlt_ctx_thread; int pipefd[2]; #endif + uint8_t enable_cursor; }WaylandContextStruct; struct debug_stream { @@ -97,6 +99,8 @@ struct debug_stream { struct weston_debug_stream_v1 *obj; }; +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + static const char *left_ptrs[] = { "left_ptr", "default", @@ -105,12 +109,18 @@ static const char *left_ptrs[] = { }; static BkGndSettingsStruct* -get_bkgnd_settings(void) +get_bkgnd_settings_cursor_info(WaylandContextStruct* wlcontext) { BkGndSettingsStruct* bkgnd_settings; char *option; char *end; + option = getenv("IVI_CLIENT_ENABLE_CURSOR"); + if(option) + wlcontext->enable_cursor = (uint8_t)strtol(option, &end, 0); + else + wlcontext->enable_cursor = 0; + bkgnd_settings = (BkGndSettingsStruct*)calloc(1, sizeof(BkGndSettingsStruct)); @@ -263,12 +273,12 @@ static int create_cursors(WaylandContextStruct* wlcontext) { wlcontext->cursor = NULL; - for (j = 0; !wlcontext->cursor && j < 4; ++j) + for (j = 0; !wlcontext->cursor && j < ARRAY_SIZE(left_ptrs); ++j) wlcontext->cursor = wl_cursor_theme_get_cursor(wlcontext->cursor_theme, left_ptrs[j]); if (!wlcontext->cursor) { - fprintf(stderr, "could not load cursor '%s'\n", left_ptrs[j]); + fprintf(stderr, "could not load any cursor\n"); return -1; } @@ -470,9 +480,11 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, &ivi_application_interface, 1); } else if (!strcmp(interface, "wl_seat")) { - wlcontext->wl_seat = + if (wlcontext->enable_cursor) { + wlcontext->wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); - wl_seat_add_listener(wlcontext->wl_seat, &seat_Listener, data); + wl_seat_add_listener(wlcontext->wl_seat, &seat_Listener, data); + } } #ifdef LIBWESTON_DEBUG_PROTOCOL else if (!strcmp(interface, weston_debug_v1_interface.name)) { @@ -691,20 +703,19 @@ static void * weston_dlt_thread_function(void *data) { WaylandContextStruct* wlcontext; + +#ifdef DLT + /*init dlt*/ char apid[DLT_ID_SIZE]; char ctid[DLT_ID_SIZE]; - char *temp; DLT_DECLARE_CONTEXT(weston_dlt_context) - - wlcontext = (WaylandContextStruct*)data; - - /*init dlt*/ dlt_set_id(apid, WESTON_DLT_APP); dlt_set_id(ctid, WESTON_DLT_CONTEXT); DLT_REGISTER_APP(apid, WESTON_DLT_APP_DESC); DLT_REGISTER_CONTEXT(weston_dlt_context, ctid, WESTON_DLT_CONTEXT_DESC); - +#endif + wlcontext = (WaylandContextStruct*)data; /*make the stdin as read end of the pipe*/ dup2(wlcontext->pipefd[0], STDIN_FILENO); @@ -716,17 +727,25 @@ weston_dlt_thread_function(void *data) /* read from std-in(read end of pipe) till newline char*/ do { i++; - read(wlcontext->pipefd[0], &str[i], 1); + if(read(wlcontext->pipefd[0], &str[i], 1) < 0) + printf("read failed : %s", strerror(errno)); } while (str[i] != '\n'); if (strcmp(str,"")!=0) { +#ifdef DLT DLT_LOG(weston_dlt_context, DLT_LOG_INFO, DLT_STRING(str)); +#else + fprintf(stderr,"%s",str); +#endif } } +#ifdef DLT DLT_UNREGISTER_CONTEXT(weston_dlt_context); DLT_UNREGISTER_APP(); +#endif + pthread_exit(NULL); } #endif @@ -803,7 +822,6 @@ int main (int argc, const char * argv[]) BkGndSettingsStruct* bkgnd_settings; struct sigaction sigint; - int offset = 0; int ret = 0; sigint.sa_handler = signal_int; @@ -812,11 +830,12 @@ int main (int argc, const char * argv[]) sigaction(SIGTERM, &sigint, NULL); sigaction(SIGSEGV, &sigint, NULL); + wlcontext = (WaylandContextStruct*)calloc(1, sizeof(WaylandContextStruct)); + /*get bkgnd settings and create shm-surface*/ - bkgnd_settings = get_bkgnd_settings(); + bkgnd_settings = get_bkgnd_settings_cursor_info(wlcontext); /*init wayland context*/ - wlcontext = (WaylandContextStruct*)calloc(1, sizeof(WaylandContextStruct)); wlcontext->bkgnd_settings = bkgnd_settings; #ifdef LIBWESTON_DEBUG_PROTOCOL @@ -848,7 +867,9 @@ int main (int argc, const char * argv[]) * stdin - read end * weston will write to stdout and the * dlt_ctx_thread will read from stdin */ - pipe(wlcontext->pipefd); + if((pipe(wlcontext->pipefd)) < 0) + printf("Error in pipe() processing : %s", strerror(errno)); + dup2(wlcontext->pipefd[1], STDOUT_FILENO); wlcontext->thread_running = 1; @@ -866,24 +887,8 @@ int main (int argc, const char * argv[]) Error: #ifdef LIBWESTON_DEBUG_PROTOCOL - weston_debug_v1_destroy(wlcontext->debug_iface); - - while (1) { - struct debug_stream *stream; - int empty = 1; - - wl_list_for_each(stream, &wlcontext->stream_list, link) - if (stream->obj) { - empty = 0; - break; - } - - if (empty) - break; - - if (wl_display_dispatch(wlcontext->wl_display) < 0) - break; - } + if(wlcontext->debug_iface) + weston_debug_v1_destroy(wlcontext->debug_iface); destroy_streams(wlcontext); wl_display_roundtrip(wlcontext->wl_display); diff --git a/protocol/CMakeLists.txt b/protocol/CMakeLists.txt index 529f148..548c8ba 100644 --- a/protocol/CMakeLists.txt +++ b/protocol/CMakeLists.txt @@ -60,6 +60,11 @@ add_library(${PROJECT_NAME} SHARED ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-protocol.c ) +target_link_libraries ( + ${PROJECT_NAME} + ${WAYLAND_CLIENT_LIBRARIES} +) + set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-fPIC") diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml index 8f24226..ad9fbf5 100644 --- a/protocol/ivi-application.xml +++ b/protocol/ivi-application.xml @@ -30,7 +30,7 @@ <request name="destroy" type="destructor"> <description summary="destroy ivi_surface"> - This removes link from ivi_id to wl_surface and destroys ivi_surface. + This removes the link from ivi_id to wl_surface and destroys ivi_surface. The ID, ivi_id, is free and can be used for surface_create again. </description> </request> @@ -58,7 +58,7 @@ <description summary="create ivi-style surfaces"> This interface is exposed as a global singleton. This interface is implemented by servers that provide IVI-style user interfaces. - It allows clients to associate a ivi_surface with wl_surface. + It allows clients to associate an ivi_surface with wl_surface. </description> <enum name="error"> @@ -77,15 +77,15 @@ 3. destroy the ivi_surface 4. create ivi_surface for the wl_surface (with the same or another ivi_id as before) - surface_create will create a interface:ivi_surface with numeric ID; ivi_id in + surface_create will create an interface:ivi_surface with numeric ID; ivi_id in ivi compositor. These ivi_ids are defined as unique in the system to identify it inside of ivi compositor. The ivi compositor implements business logic how to - set properties of the surface with ivi_id according to status of the system. + set properties of the surface with ivi_id according to the status of the system. E.g. a unique ID for Car Navigation application is used for implementing special logic of the application about where it shall be located. - The server regards following cases as protocol errors and disconnects the client. - - wl_surface already has an nother role. - - ivi_id is already assigned to an another wl_surface. + The server regards the following cases as protocol errors and disconnects the client. + - wl_surface already has another role. + - ivi_id is already assigned to another wl_surface. If client destroys ivi_surface or wl_surface which is assigne to the ivi_surface, ivi_id which is assigned to the ivi_surface is free for reuse. diff --git a/weston-ivi-shell/src/ivi-controller.c b/weston-ivi-shell/src/ivi-controller.c index 5a5e17c..cabd31b 100644 --- a/weston-ivi-shell/src/ivi-controller.c +++ b/weston-ivi-shell/src/ivi-controller.c @@ -43,6 +43,7 @@ #define IVI_CLIENT_SURFACE_ID_ENV_NAME "IVI_CLIENT_SURFACE_ID" #define IVI_CLIENT_DEBUG_SCOPES_ENV_NAME "IVI_CLIENT_DEBUG_STREAM_NAMES" +#define IVI_CLIENT_ENABLE_CURSOR_ENV_NAME "IVI_CLIENT_ENABLE_CURSOR" struct ivilayer; struct iviscreen; @@ -837,10 +838,14 @@ calc_trans_matrix(struct weston_geometry *source_rect, source_center_y = source_rect->y + source_rect->height * 0.5f; weston_matrix_translate(m, -source_center_x, -source_center_y, 0.0f); - scale_x = ((float)dest_rect->width) / source_rect->width; - scale_y = ((float)dest_rect->height) / source_rect->height; + if ((dest_rect->width != source_rect->width) || + (dest_rect->height != source_rect->height)) + { + scale_x = ((float)dest_rect->width) / source_rect->width; + scale_y = ((float)dest_rect->height) / source_rect->height; - weston_matrix_scale(m, scale_x, scale_y, 1.0f); + weston_matrix_scale(m, scale_x, scale_y, 1.0f); + } translate_x = dest_rect->width * 0.5f + dest_rect->x; translate_y = dest_rect->height * 0.5f + dest_rect->y; @@ -1565,7 +1570,7 @@ output_destroyed_event(struct wl_listener *listener, void *data) destroy_screen(iviscrn); } - if (shell->bkgnd_view) + if (shell->bkgnd_view && shell->client) set_bkgnd_surface_prop(shell); else weston_compositor_schedule_repaint(shell->compositor); @@ -1576,7 +1581,7 @@ output_resized_event(struct wl_listener *listener, void *data) { struct ivishell *shell = wl_container_of(listener, shell, output_destroyed); - if (shell->bkgnd_view) + if (shell->bkgnd_view && shell->client) set_bkgnd_surface_prop(shell); } @@ -1588,7 +1593,7 @@ output_created_event(struct wl_listener *listener, void *data) create_screen(shell, created_output); - if (shell->bkgnd_view) + if (shell->bkgnd_view && shell->client) set_bkgnd_surface_prop(shell); else weston_compositor_schedule_repaint(shell->compositor); @@ -1985,6 +1990,10 @@ get_config(struct weston_compositor *compositor, struct ivishell *shell) "bkgnd-color", &shell->bkgnd_color, 0xFF000000); + weston_config_section_get_bool(section, + "enable-cursor", + &shell->enable_cursor, 0); + wl_array_init(&shell->screen_ids); while (weston_config_next_section(config, §ion, &name)) { @@ -2028,6 +2037,11 @@ ivi_shell_destroy(struct wl_listener *listener, void *data) struct ivishell *shell = wl_container_of(listener, shell, destroy_listener); + if (shell->client) { + wl_list_remove(&shell->client_destroy_listener.link); + wl_client_destroy(shell->client); + } + wl_list_remove(&shell->destroy_listener.link); wl_list_remove(&shell->output_created.link); @@ -2160,6 +2174,18 @@ load_input_module(struct ivishell *shell) } static void +ivi_shell_client_destroy(struct wl_listener *listener, void *data) +{ + struct ivishell *shell = wl_container_of(listener, shell, + client_destroy_listener); + + weston_log("ivi shell client %p destroyed \n", shell->client); + + wl_list_remove(&shell->client_destroy_listener.link); + shell->client = NULL; +} + +static void launch_client_process(void *data) { struct ivishell *shell = @@ -2172,10 +2198,18 @@ launch_client_process(void *data) setenv(IVI_CLIENT_DEBUG_SCOPES_ENV_NAME, shell->debug_scopes, 0x1); free(shell->debug_scopes); } + if(shell->enable_cursor) { + sprintf(option, "%d", shell->enable_cursor); + setenv(IVI_CLIENT_ENABLE_CURSOR_ENV_NAME, option, 0x1); + } shell->client = weston_client_start(shell->compositor, shell->ivi_client_name); + shell->client_destroy_listener.notify = ivi_shell_client_destroy; + wl_client_add_destroy_listener(shell->client, + &shell->client_destroy_listener); + free(shell->ivi_client_name); } diff --git a/weston-ivi-shell/src/ivi-controller.h b/weston-ivi-shell/src/ivi-controller.h index c279146..16dbe57 100644 --- a/weston-ivi-shell/src/ivi-controller.h +++ b/weston-ivi-shell/src/ivi-controller.h @@ -24,7 +24,7 @@ #define WESTON_IVI_SHELL_SRC_IVI_CONTROLLER_H_ #include "ivi-wm-server-protocol.h" -#include <weston/ivi-layout-export.h> +#include <ivi-layout-export.h> /* Convert timespec to milliseconds * @@ -80,11 +80,14 @@ struct ivishell { struct wl_listener destroy_listener; + struct wl_listener client_destroy_listener; + struct wl_array screen_ids; uint32_t screen_id_offset; int32_t bkgnd_surface_id; uint32_t bkgnd_color; + int enable_cursor; struct ivisurface *bkgnd_surface; struct weston_layer bkgnd_layer; struct weston_view *bkgnd_view; |