From 2e731255404e0efb0df1ede8d0b0a32ac011b420 Mon Sep 17 00:00:00 2001 From: Volodymyr Riazantsev Date: Sat, 16 Jul 2016 02:53:25 -0400 Subject: [PATCH] ivi-shell: Add autolaunch and launch rules functionality Add ability to select application for autolaunch. Also launch rules settings are added. Signed-off-by: Volodymyr Riazantsev Signed-off-by: Karthik Ramanan --- ivi-shell/ivi-layout-controller-ti.c | 293 +++++++++++++++++++++++++++++++---- 1 file changed, 259 insertions(+), 34 deletions(-) diff --git a/ivi-shell/ivi-layout-controller-ti.c b/ivi-shell/ivi-layout-controller-ti.c index b7cf436..4a2d648 100644 --- a/ivi-shell/ivi-layout-controller-ti.c +++ b/ivi-shell/ivi-layout-controller-ti.c @@ -27,6 +27,9 @@ #include #include +#include +#include + #include "ivi-layout-export.h" #ifndef container_of @@ -56,13 +59,24 @@ if (__dl__ & debug_level) \ #define pr_wrn(...) __print_log(DL_WRN, "W: " __VA_ARGS__) #define TRACE() __print_log(DL_DBG, "TR: %s - %d\n", __func__, __LINE__) - -#define WINDOWS_TITLE_HEIGHT 30 #define DEFAULT_SURFACE_ID_FOR_WL_SHELL_APP 0x80000000 /***************************************************************************** * structure, globals ****************************************************************************/ + +struct hmi_launch_rule { +#define MAX_APP_NAME_LEN 64 + char app_name[MAX_APP_NAME_LEN]; + int screen_id; + int order; + int autofocus; + int mode; + int32_t src_rect[4]; + int32_t dest_rect[4]; + int32_t crop_rect[4]; +}; + struct hmi_controller_layer { struct ivi_layout_layer *ivilayer; uint32_t id_layer; @@ -75,6 +89,7 @@ struct hmi_controller_layer { struct wl_list link; struct wl_list screen_link; struct wl_list surfaces_list; + struct hmi_launch_rule *rule; }; struct hmi_controller_surface { @@ -82,6 +97,7 @@ struct hmi_controller_surface { void *ivisurf; struct wl_list link; struct wl_listener destroy_listener; + int conf_num; }; struct hmi_controller_screen { @@ -93,6 +109,8 @@ struct hmi_server_setting { uint32_t base_layer_id; int32_t panel_height; char *ivi_homescreen; + char *homescreen_app; + struct wl_array rules; }; struct hmi_controller { @@ -108,6 +126,7 @@ struct hmi_controller { struct wl_listener destroy_listener; struct wl_client *user_interface; struct wl_list layers_list; + }; const struct ivi_controller_interface *ivi_controller_interface; @@ -143,6 +162,42 @@ mem_alloc(size_t size, char *file, int32_t line) #define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__) +static int +get_process_name_by_pid(pid_t pid, char *name, int size) +{ + char proc_name[256] = "/proc/"; + char n[512] = {0}; + char *_n; + + sprintf(&proc_name[strlen(proc_name)], "%d/exe", (int)pid); + + if (!name + || access(proc_name, R_OK) + || (readlink(proc_name, n, sizeof(n)) <= 0)) { + + return -1; + } + + _n = strrchr(n, '/'); + strncpy(name, _n ? (_n + 1) : n, size); + + return 0; +} + +static struct hmi_launch_rule +*get_rule(struct wl_array *arr, const char *app_name) +{ + struct hmi_launch_rule *rule = NULL; + + wl_array_for_each(rule, arr) { + if (!strcmp(app_name, rule->app_name)) + return rule; + } + + return NULL; +} + + /** * Internal method to create ivi_layer with hmi_controller_layer and * add to a ivi_screen @@ -177,6 +232,42 @@ create_layer(struct ivi_layout_screen *iviscrn, } +static void +register_layer_on_screen(struct hmi_controller *hmi_ctrl, + int i, + struct hmi_controller_layer *nlayer) +{ + unsigned cnt, j = 0; + struct hmi_controller_layer *layer = NULL; + struct ivi_layout_layer **layers; + + if (nlayer->rule && nlayer->rule->order == 0) { + wl_list_insert(&hmi_ctrl->screens[i].layers_list, &nlayer->screen_link); + } else { + wl_list_for_each(layer, &hmi_ctrl->screens[i].layers_list, screen_link) { + if (layer->rule && (layer->rule->order == 0)) + continue; + else + break; + } + wl_list_insert(layer->screen_link.prev, &nlayer->screen_link); + } + + cnt = wl_list_length(&hmi_ctrl->screens[i].layers_list); + + layers = calloc(cnt, sizeof(*layers)); + + wl_list_for_each_reverse(layer, &hmi_ctrl->screens[i].layers_list, screen_link) { + layers[j++] = layer->ivilayer; + } + + ivi_controller_interface->screen_set_render_order(hmi_ctrl->screens[i].iviscrn, layers, cnt); + + free(layers); + + ivi_controller_interface->commit_changes(); +} + static struct hmi_controller_layer *get_layer_for_surface(struct hmi_controller *hmi_ctrl , struct ivi_layout_surface *ivisurf @@ -188,6 +279,9 @@ static struct hmi_controller_layer struct wl_client *client; struct ivi_layout_screen *iviscrn = NULL; struct weston_output *output = NULL; + char proc_name[256]; + struct hmi_launch_rule *rule; + pid_t pid; uid_t uid; gid_t gid; @@ -213,13 +307,21 @@ static struct hmi_controller_layer pr_dbg("Existed layer for PID=%d was not found. Creating new\n", pid); - for(;; i++) { - if (wl_list_empty(&hmi_ctrl->screens[i].layers_list) || - (i == (hmi_ctrl->screens_count - 1))) - break; - }; + get_process_name_by_pid(pid, proc_name, sizeof(proc_name)); - iviscrn = hmi_ctrl->screens[i].iviscrn; + rule = get_rule(&hmi_ctrl->hmi_setting->rules, proc_name); + + if (rule && (rule->screen_id >= 0) && (rule->screen_id < hmi_ctrl->screens_count)) { + iviscrn = hmi_ctrl->screens[rule->screen_id].iviscrn; + i = rule->screen_id; + } else { + for(;; i++) { + if (wl_list_empty(&hmi_ctrl->screens[i].layers_list) || + (i == (hmi_ctrl->screens_count - 1))) + break; + }; + iviscrn = hmi_ctrl->screens[i].iviscrn; + } layer = calloc(1, sizeof *layer); @@ -230,14 +332,16 @@ static struct hmi_controller_layer wl_list_init(&layer->surfaces_list); layer->width = output->width; - layer->height = output->height + WINDOWS_TITLE_HEIGHT; + layer->height = output->height; layer->id_layer = hmi_ctrl->hmi_setting->base_layer_id++; layer->pid = pid; + layer->rule = rule; create_layer(iviscrn, layer); wl_list_insert(&hmi_ctrl->layers_list, &layer->link); - wl_list_insert(&hmi_ctrl->screens[i].layers_list, &layer->screen_link); + + register_layer_on_screen(hmi_ctrl, i, layer); return layer; @@ -350,41 +454,77 @@ set_notification_configure_surface(struct ivi_layout_surface *ivisurf, struct hmi_controller_layer *hmi_ctrl_layer = NULL; struct weston_surface *surface; struct hmi_controller_surface *hmi_ctrl_surf = NULL; + int src_rect[4] = {0}; + int dest_rect[4] = {0}; wl_list_for_each(hmi_ctrl_layer, &hmi_ctrl->layers_list, link) { wl_list_for_each(hmi_ctrl_surf, &hmi_ctrl_layer->surfaces_list, link) { if (hmi_ctrl_surf->ivisurf == ivisurf) { - pr_dbg("Surface was already configured. Skip add to list\n"); goto found; } } } - hmi_ctrl_layer = NULL; + return; found: surface = ivi_controller_interface->surface_get_weston_surface(ivisurf); - if (surface) { - - ivi_controller_interface->surface_set_source_rectangle( - ivisurf, 0, WINDOWS_TITLE_HEIGHT, surface->width, - surface->height); - -#if 0 - ivi_controller_interface->surface_set_destination_rectangle( - ivisurf, 0, 0, surface->width, surface->height); -#else - if (hmi_ctrl_layer) { - ivi_controller_interface->surface_set_destination_rectangle( - ivisurf, 0, 0, hmi_ctrl_layer->width, hmi_ctrl_layer->height); - } else { - ivi_controller_interface->surface_set_destination_rectangle( - ivisurf, 0, 0, surface->width, surface->height); + if (!surface) + return; + + src_rect[2] = dest_rect[2] = surface->width; + src_rect[3] = dest_rect[3] = surface->height; + + if (hmi_ctrl_layer && hmi_ctrl_layer->rule) { + + if (hmi_ctrl_layer->rule->mode >= 0) { + switch (hmi_ctrl_layer->rule->mode) { + case 1: + dest_rect[2] = hmi_ctrl_layer->width; + dest_rect[3] = hmi_ctrl_layer->height; + break; + + default: + /* No changes, using requested size */ + break; + } + } + + if (hmi_ctrl_layer->rule->crop_rect[0] >= 0) { + src_rect[0] += hmi_ctrl_layer->rule->crop_rect[0]; + src_rect[1] += hmi_ctrl_layer->rule->crop_rect[1]; + src_rect[2] -= (hmi_ctrl_layer->rule->crop_rect[0] + + hmi_ctrl_layer->rule->crop_rect[2]); + src_rect[3] -= (hmi_ctrl_layer->rule->crop_rect[1] + + hmi_ctrl_layer->rule->crop_rect[3]); + } + + if (hmi_ctrl_layer->rule->dest_rect[0] >= 0 || + hmi_ctrl_layer->rule->dest_rect[1] >= 0 || + hmi_ctrl_layer->rule->dest_rect[2] >= 0 || + hmi_ctrl_layer->rule->dest_rect[3] >= 0) { + + dest_rect[0] = hmi_ctrl_layer->rule->dest_rect[0]; + dest_rect[1] = hmi_ctrl_layer->rule->dest_rect[1]; + dest_rect[2] = hmi_ctrl_layer->rule->dest_rect[2] > 0 ? + hmi_ctrl_layer->rule->dest_rect[2] : dest_rect[2] ; + dest_rect[3] = hmi_ctrl_layer->rule->dest_rect[3] > 0 ? + hmi_ctrl_layer->rule->dest_rect[3] : dest_rect[3] ; } -#endif - ivi_controller_interface->surface_set_visibility(ivisurf, true); - ivi_controller_interface->commit_changes(); } + + ivi_controller_interface->surface_set_source_rectangle(ivisurf + , src_rect[0], src_rect[1] + , src_rect[2], src_rect[3]); + + ivi_controller_interface->surface_set_destination_rectangle(ivisurf + , dest_rect[0], dest_rect[1] + , dest_rect[2], dest_rect[3]); + + ivi_controller_interface->surface_set_visibility(ivisurf, true); + ivi_controller_interface->commit_changes(); + + hmi_ctrl_surf->conf_num++; } static struct hmi_server_setting * @@ -393,6 +533,9 @@ hmi_server_setting_create(struct weston_compositor *ec) struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting)); struct weston_config *config = ec->config; struct weston_config_section *shell_section = NULL; + const char *name = NULL; + + setting->panel_height = 30; shell_section = weston_config_get_section(config, "ivi-shell", NULL, NULL); @@ -400,7 +543,78 @@ hmi_server_setting_create(struct weston_compositor *ec) weston_config_section_get_uint(shell_section, "base-layer-id", &setting->base_layer_id, 1000); - setting->panel_height = 30; + if ((shell_section = weston_config_get_section(config, "ivi-autolaunch", + NULL, NULL))) { + weston_config_section_get_string(shell_section, "path", + &setting->homescreen_app, NULL); + } + + + wl_array_init(&setting->rules); + + while (weston_config_next_section(config, &shell_section, &name)) { + int screen_id; + int order; + int mode; + int focus_on; + int crop_rect[4] = {-1, -1, -1, -1}; + int src_rect[4] = {-1, -1, -1, -1}; + int dest_rect[4] = {-1, -1, -1, -1}; + char *app_name; + char *buff; + struct hmi_launch_rule *rule = NULL; + + if (0 != strcmp(name, "ivi-layout-rule")) + continue; + + if (0 != weston_config_section_get_string(shell_section, "application", + &app_name, NULL)) + continue; + + weston_config_section_get_int(shell_section, "order", &order, -1); + weston_config_section_get_int(shell_section, "mode", &mode, -1); + weston_config_section_get_int(shell_section, "focus_on", &focus_on, -1); + weston_config_section_get_int(shell_section, "screen", &screen_id, -1); + + if (0 == weston_config_section_get_string(shell_section, "crop_rect", + &buff, NULL)) { + sscanf(buff, "%d,%d,%d,%d", crop_rect + 0, + crop_rect + 1, + crop_rect + 2, + crop_rect + 3); + } + + if (0 == weston_config_section_get_string(shell_section, "src_rect", + &buff, NULL)) { + sscanf(buff, "%d,%d,%d,%d", src_rect + 0, + src_rect + 1, + src_rect + 2, + src_rect + 3); + } + + if (0 == weston_config_section_get_string(shell_section, "dest_rect", + &buff, NULL)) { + sscanf(buff, "%d,%d,%d,%d", dest_rect + 0, + dest_rect + 1, + dest_rect + 2, + dest_rect + 3); + } + + rule = wl_array_add(&setting->rules, sizeof(*rule)); + + if (rule) { + rule->screen_id = screen_id; + rule->order = order; + rule->mode = mode; + rule->autofocus = focus_on; + + strncpy(rule->app_name, app_name, sizeof(rule->app_name)); + + memcpy(rule->src_rect, src_rect, sizeof(rule->src_rect)); + memcpy(rule->dest_rect, dest_rect, sizeof(rule->dest_rect)); + memcpy(rule->crop_rect, crop_rect, sizeof(rule->crop_rect)); + } + } return setting; } @@ -415,6 +629,15 @@ hmi_controller_destroy(struct wl_listener *listener, void *data) free(hmi_ctrl); } +static void hmi_controller_launch_homescreen(struct hmi_controller *hmi_ctrl) +{ + if (hmi_ctrl->hmi_setting->homescreen_app) { + if(system(hmi_ctrl->hmi_setting->homescreen_app)) { + ; + } + } +} + static struct hmi_controller * hmi_controller_create(struct weston_compositor *ec) { @@ -429,9 +652,10 @@ hmi_controller_create(struct weston_compositor *ec) ivi_controller_interface->get_screens(&screen_length, &pp_screen); - for (i = screen_length; i-- ; j++) { + for (i = screen_length; i--;) { iviscrn = pp_screen[i]; + j = ivi_controller_interface->get_id_of_screen(iviscrn); hmi_ctrl->screens[j].iviscrn = iviscrn; wl_list_init(&hmi_ctrl->screens[i].layers_list); @@ -506,7 +730,6 @@ controller_module_init(struct weston_compositor *ec, { struct hmi_controller *hmi_ctrl = NULL; - if (interface_version < sizeof(struct ivi_controller_interface)) { weston_log("ivi-layout-controller-ti: version mismatch of controller interface"); return -1; @@ -528,5 +751,7 @@ controller_module_init(struct weston_compositor *ec, weston_log("ivi-layout-controller-ti: Successfully started."); + hmi_controller_launch_homescreen(hmi_ctrl); + return 0; } -- 2.4.5