X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fvirtual_window.c;h=1d918782aaeae3e5837f729c1b192e81f86ff829;hb=888ee28916d99ce45d4916815dd666a62451f7da;hp=66f42ed48422e37a317e93699260a08921bbe41d;hpb=65dfdebd0137c3361d066686c8986f92aa972bd9;p=apps%2Fnative%2Fwidget%2Fwidget.git diff --git a/src/virtual_window.c b/src/virtual_window.c index 66f42ed..1d91878 100644 --- a/src/virtual_window.c +++ b/src/virtual_window.c @@ -24,6 +24,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -34,7 +38,9 @@ #include #include #include +#include #include +#include #include "widget.h" #include "widget_internal.h" @@ -50,6 +56,24 @@ #define WIDGET_DEFAULT_WIDTH 1 #define WIDGET_DEFAULT_HEIGHT 1 +#define MOUSE_BUTTON_LEFT 1 + +/** + * @note + * Supported touch devices are limited to 32. + * Because of count of bits of integer type. (32 bits) + */ +#define MAX_DEVICE 32 + +#define IS_PRESSED(info, device) (((device) < MAX_DEVICE) ? (((info)->pressed & (0x01 << (device))) == (0x01 << (device))) : 0) + +/** + * @note + * Short-Circuit + */ +#define SET_PRESSED(info, device) ((void)(((device) < MAX_DEVICE) && (((info)->pressed |= (0x01 << (device)))))) +#define SET_RELEASED(info, device) ((void)(((device) < MAX_DEVICE) && (((info)->pressed &= (~(0x01 << (device))))))) + static inline Evas_Object *get_highlighted_object(Evas_Object *obj) { Evas_Object *o, *ho; @@ -105,62 +129,14 @@ static inline void apply_orientation(int degree, int *x, int *y, int width, int } } -/** - * @note - * Every user event (mouse) on the buffer will be passed via this event callback - */ -static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_data *event_info, void *data) +static inline int processing_events(vwin_info_t info, widget_buffer_event_data_t event_info, double timestamp) { - vwin_info_t info = data; Elm_Access_Action_Info action_info; Elm_Access_Action_Type action_type; - int ret = 0; Evas_Object *parent_elm; KeySym *key_symbol; unsigned int flags = 0; - double timestamp; - - if (!info || info->state != VWIN_INFO_CREATED || !info->handle) { - /* Just ignore this event */ - return 0; - } - - if (WIDGET_CONF_USE_GETTIMEOFDAY) { - if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) { - struct timeval tv; - - if (gettimeofday(&tv, NULL) < 0) { - ErrPrint("gettimeofday: %d\n", errno); - } else { - timestamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f; - timestamp -= event_info->timestamp; - - if (timestamp > WIDGET_CONF_EVENT_FILTER) { - DbgPrint("Dropped %lf\n", timestamp); - return 0; - } - } - } - - /** - * If the device doesn't use the clock monotic time, we have to emulate it for EVAS - * Evas only use the monotic time for animating objects - */ - timestamp = ecore_time_get() * 1000.0f; - } else { - if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) { - timestamp = ecore_time_get(); - - timestamp -= event_info->timestamp; - if (timestamp > WIDGET_CONF_EVENT_FILTER) { - DbgPrint("Dropped %lf\n", timestamp); - return 0; - } - } - - timestamp = event_info->timestamp * 1000.0f; - } - + int ret = 0; /** * @note * Feed up events @@ -171,6 +147,9 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ flags |= EVAS_EVENT_FLAG_ON_HOLD; evas_event_default_flags_set(info->e, flags); ErrPrint("ON_HOLD[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp); + if (info->pressed == 0) { + info->flags.field.on_hold_before_down = 1; + } break; case WIDGET_BUFFER_EVENT_OFF_HOLD: flags = evas_event_default_flags_get(info->e); @@ -181,6 +160,9 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ flags = evas_event_default_flags_get(info->e); flags |= EVAS_EVENT_FLAG_ON_SCROLL; evas_event_default_flags_set(info->e, flags); + if (info->pressed == 0) { + info->flags.field.on_scroll_before_down = 1; + } break; case WIDGET_BUFFER_EVENT_OFF_SCROLL: flags = evas_event_default_flags_get(info->e); @@ -196,11 +178,21 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ case WIDGET_BUFFER_EVENT_DOWN: apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source); - if (info->pressed) { + if (IS_PRESSED(info, event_info->info.pointer.device)) { ErrPrint("MOUSE UP is not called\n"); - ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp); - evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); - evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); + ErrPrint("UP[%s] %dx%d - %lf (%d)\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, event_info->info.pointer.device); + if (event_info->info.pointer.device > 0) { + /** + * @multi touch up + */ + evas_event_feed_multi_up(info->e, event_info->info.pointer.device, event_info->info.pointer.x, event_info->info.pointer.y, + 0.0f, 0.0f, 0.0f, /* radius, radius_x, radius_y */ + 0.0f, 0.0f, 0.0f, 0.0f, /* pressure, angle, fx, fy */ + EVAS_BUTTON_NONE, timestamp, NULL); /* button_flags, timestamp, ... */ + } else { + evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); + evas_event_feed_mouse_up(info->e, MOUSE_BUTTON_LEFT, EVAS_BUTTON_NONE, timestamp, NULL); + } } /** @@ -208,19 +200,42 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ * Before processing the DOWN event, * Reset the evas event flags regarding ON_HOLD option. * It can be re-enabled while processing down-move-up events. + * However if those events are occurred right before DOWN, + * Do not clear it. + * Some speicific cases, the ON_HOLD(ON_SCROLL) event can be delievered + * before MOUSE_DOWN event. */ flags = evas_event_default_flags_get(info->e); - flags &= ~EVAS_EVENT_FLAG_ON_SCROLL; - flags &= ~EVAS_EVENT_FLAG_ON_HOLD; + if (!info->flags.field.on_hold_before_down) { + flags &= ~EVAS_EVENT_FLAG_ON_HOLD; + } + if (!info->flags.field.on_scroll_before_down) { + flags &= ~EVAS_EVENT_FLAG_ON_SCROLL; + } evas_event_default_flags_set(info->e, flags); + + /** + * @note + * Reset flags after dealing with the ON_HOLD/ON_SCROLL event + */ + info->flags.field.on_scroll_before_down = 0; + info->flags.field.on_hold_before_down = 0; /** * @note * Calculate the event occurred X & Y on the buffer */ - evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); - evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); /* + 0.2f just for fake event */ - info->pressed = 1; - ErrPrint("DOWN[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp); + if (event_info->info.pointer.device > 0) { + evas_event_feed_multi_down(info->e, event_info->info.pointer.device, event_info->info.pointer.x, event_info->info.pointer.y, + 0.0f, 0.0f, 0.0f, /* radius, radius_x, radius_y */ + 0.0f, 0.0f, 0.0f, 0.0f, /* pressure, angle, fx, fy */ + EVAS_BUTTON_NONE, timestamp, NULL); /* button_flags, timestamp, ... */ + } else { + evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); + evas_event_feed_mouse_down(info->e, MOUSE_BUTTON_LEFT, EVAS_BUTTON_NONE, timestamp, NULL); /* + 0.2f just for fake event */ + } + + SET_PRESSED(info, event_info->info.pointer.device); + ErrPrint("DOWN[%s] %dx%d - %lf (%d)\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, event_info->info.pointer.device); break; case WIDGET_BUFFER_EVENT_MOVE: apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source); @@ -228,20 +243,35 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ * @note * Calculate the event occurred X & Y on the buffer */ - evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); + if (event_info->info.pointer.device > 0) { + evas_event_feed_multi_move(info->e, event_info->info.pointer.device, event_info->info.pointer.x, event_info->info.pointer.y, + 0.0f, 0.0f, 0.0f, /* radius, radius_x, radius_y */ + 0.0f, 0.0f, 0.0f, 0.0f, /* pressure, angle, fx, fy */ + timestamp, NULL); /* timestamp, ... */ + } else { + evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); + } break; case WIDGET_BUFFER_EVENT_UP: apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source); - evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); - evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); - info->pressed = 0; + + if (event_info->info.pointer.device > 0) { + evas_event_feed_multi_up(info->e, event_info->info.pointer.device, event_info->info.pointer.x, event_info->info.pointer.y, + 0.0f, 0.0f, 0.0f, /* radius, radius_x, radius_y */ + 0.0f, 0.0f, 0.0f, 0.0f, /* pressure, angle, fx, fy */ + EVAS_BUTTON_NONE, timestamp, NULL); /* button_flags, timestamp, ... */ + } else { + evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); + evas_event_feed_mouse_up(info->e, MOUSE_BUTTON_LEFT, EVAS_BUTTON_NONE, timestamp, NULL); + } + SET_RELEASED(info, event_info->info.pointer.device); /** * @note * We have to keep the event flags, so we should not clear them from here. * Sometimes, asynchronously callable Callbacks can refer the evas event flags after up event. * so if we reset them from here, those kind of callbacks will fails to do their job properly. */ - ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp); + ErrPrint("UP[%s] %dx%d - %lf (%d)\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, event_info->info.pointer.device); break; case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT: parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG); @@ -250,7 +280,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_HIGHLIGHT; + action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT; /** * @note * Calculate the event occurred X & Y on the buffer @@ -278,7 +308,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT; + action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT_NEXT; action_info.highlight_cycle = EINA_FALSE; ret = elm_access_action(parent_elm, action_type, &action_info); ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_LAST : WIDGET_ACCESS_STATUS_DONE; @@ -290,7 +320,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV; + action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT_PREV; action_info.highlight_cycle = EINA_FALSE; ret = elm_access_action(parent_elm, action_type, &action_info); ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_FIRST : WIDGET_ACCESS_STATUS_DONE; @@ -302,7 +332,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_ACTIVATE; + action_type = 0; //ELM_ACCESS_ACTION_ACTIVATE; ret = elm_access_action(parent_elm, action_type, &action_info); ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE; break; @@ -313,7 +343,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_UP; + action_type = 0; //ELM_ACCESS_ACTION_UP; ret = elm_access_action(parent_elm, action_type, &action_info); ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE; break; @@ -324,7 +354,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_DOWN; + action_type = 0; //ELM_ACCESS_ACTION_DOWN; ret = elm_access_action(parent_elm, action_type, &action_info); ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE; break; @@ -335,7 +365,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_SCROLL; + action_type = 0; //ELM_ACCESS_ACTION_SCROLL; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -349,7 +379,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_SCROLL; + action_type = 0; //ELM_ACCESS_ACTION_SCROLL; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -363,7 +393,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_SCROLL; + action_type = 0; //ELM_ACCESS_ACTION_SCROLL; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -377,7 +407,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT; + action_type = 0; //ELM_ACCESS_ACTION_UNHIGHLIGHT; ret = elm_access_action(parent_elm, action_type, &action_info); ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE; break; @@ -388,7 +418,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_VALUE_CHANGE; + action_type = 0; //ELM_ACCESS_ACTION_VALUE_CHANGE; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -402,7 +432,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_MOUSE; + action_type = 0; //ELM_ACCESS_ACTION_MOUSE; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -416,7 +446,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_BACK; + action_type = 0; //ELM_ACCESS_ACTION_BACK; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -430,7 +460,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_OVER; + action_type = 0; //ELM_ACCESS_ACTION_OVER; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -444,7 +474,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_READ; + action_type = 0; //ELM_ACCESS_ACTION_READ; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -458,7 +488,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_ENABLE; + action_type = 0; //ELM_ACCESS_ACTION_ENABLE; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -472,7 +502,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ break; } memset(&action_info, 0, sizeof(action_info)); - action_type = ELM_ACCESS_ACTION_DISABLE; + action_type = 0; //ELM_ACCESS_ACTION_DISABLE; action_info.x = event_info->info.access.x; action_info.y = event_info->info.access.y; action_info.mouse_type = event_info->info.access.mouse_type; @@ -571,6 +601,121 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ return ret; } +static Eina_Bool pended_event_consumer_cb(void *data) +{ + vwin_info_t info = data; + widget_buffer_event_data_t event_info; + + event_info = eina_list_nth(info->pended_events_list, 0); + if (!event_info) { + info->pended_events_consumer = NULL; + return ECORE_CALLBACK_CANCEL; + } + + DbgPrint("Consuming delayed events\n"); + (void)processing_events(info, event_info, event_info->timestamp); + + info->pended_events_list = eina_list_remove(info->pended_events_list, event_info); + free(event_info); + return ECORE_CALLBACK_RENEW; +} + +/** + * @note + * Every user event (mouse) on the buffer will be passed via this event callback + */ +static int event_handler_cb(widget_buffer_h handler, widget_buffer_event_data_t event_info, void *data) +{ + vwin_info_t info = data; + double timestamp; + + /** + * @note + * If the feeds event is accessibility or key event, + * "return 0" will confusing the viewer, + * because it will waiting result of event processing to do handles state properly. + */ + + if (!info || info->state != VWIN_INFO_CREATED || !info->handle || info->flags.field.deleted) { + /* Just ignore this event */ + return 0; + } + + if (event_info->type == WIDGET_BUFFER_EVENT_FRAME_SKIP_CLEARED) { + /** + * Increase the count_of_rendering only if it meets conditions. + * Or do not increase it to prevent from overflow problem. + * If we trying to increase the count_of_rendering variable, it could be overflowed. + * These conditions will prevents count_of_rendering from overflow issue. + */ + if (info->pended_events_list && !info->pended_events_consumer) { + info->pended_events_consumer = ecore_timer_add(0.0001f, pended_event_consumer_cb, info); + if (info->pended_events_consumer) { + ErrPrint("Failed to create a pended event consumer\n"); + } + } + + return 0; + } + + if (WIDGET_CONF_USE_GETTIMEOFDAY) { + if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) { + struct timeval tv; + + if (gettimeofday(&tv, NULL) < 0) { + ErrPrint("gettimeofday: %d\n", errno); + } else { + timestamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f; + timestamp -= event_info->timestamp; + + if (timestamp > WIDGET_CONF_EVENT_FILTER) { + DbgPrint("Dropped %lf\n", timestamp); + return 0; + } + } + } + + /** + * If the device doesn't use the clock monotic time, we have to emulate it for EVAS + * Evas only use the monotic time for animating objects + */ + timestamp = ecore_time_get() * 1000.0f; + } else { + if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) { + timestamp = ecore_time_get(); + + timestamp -= event_info->timestamp; + if (timestamp > WIDGET_CONF_EVENT_FILTER) { + DbgPrint("Dropped %lf\n", timestamp); + return 0; + } + } + + timestamp = event_info->timestamp * 1000.0f; + } + + if ((info->w <= 1 && info->h <= 1) || widget_provider_buffer_frame_skip(info->handle) > 0 || info->pended_events_list) { + widget_buffer_event_data_t _ev_info; + _ev_info = malloc(sizeof(*_ev_info)); + if (_ev_info) { + memcpy(_ev_info, event_info, sizeof(*_ev_info)); + info->pended_events_list = eina_list_append(info->pended_events_list, _ev_info); + _ev_info->timestamp = timestamp; + /** + * @note + * Push events to pending list,. + * Consuming it first. + */ + DbgPrint("Canvas is not prepared. pending the events (%dx%d)\n", info->w, info->h); + return 0; + } else { + ErrPrint("malloc: %d\n", errno); + } + } + + return processing_events(info, event_info, timestamp); +} + static void pre_render_cb(void *data, Evas *e, void *event_info) { vwin_info_t info = data; @@ -579,7 +724,7 @@ static void pre_render_cb(void *data, Evas *e, void *event_info) return; } - if (widget_conf_premultiplied_alpha()) { + if (WIDGET_CONF_PREMULTIPLIED_COLOR) { Evas_Coord w; Evas_Coord h; @@ -598,32 +743,43 @@ static void pre_render_cb(void *data, Evas *e, void *event_info) } } +static inline void dump_to_file(void *buffer, int size, const char *fname) +{ + int fd; + + fd = open(fname, O_WRONLY | O_CREAT, 0644); + if (fd >= 0) { + if (write(fd, buffer, size) != size) { + ErrPrint("write: %d\n", errno); + } + + if (close(fd) < 0) { + ErrPrint("close: %d\n", errno); + } + } +} + static void post_render_cb(void *data, Evas *e, void *event_info) { vwin_info_t info = data; + const char *ee_key; if (!info || info->state != VWIN_INFO_CREATED || !info->handle) { return; } - if (widget_conf_premultiplied_alpha()) { - void *canvas; - int x, y, w, h; - - // Get a pointer of a buffer of the virtual canvas - canvas = (void *)ecore_evas_buffer_pixels_get(info->ee); - if (!canvas) { - ErrPrint("Failed to get pixel canvas\n"); + ee_key = WIDGET_CONF_EE_KEY_FOR_UPDATE; + if (ee_key) { + const char *value; + value = ecore_evas_data_get(info->ee, ee_key); + if (value && strcmp(value, "true")) { + DbgPrint("Frame skipped[%s]\n", value); return; } - - ecore_evas_geometry_get(info->ee, &x, &y, &w, &h); - evas_data_argb_unpremul(canvas, w * h); + ecore_evas_data_set(info->ee, ee_key, "false"); } - if (info->type == VWIN_GEM) { - widget_buffer_post_render(info->handle); - } else if (info->type == VWIN_PIXMAP) { + if (info->type == VWIN_PIXMAP) { int idx; unsigned int front_resource_id; @@ -631,26 +787,113 @@ static void post_render_cb(void *data, Evas *e, void *event_info) for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) { if (front_resource_id == info->resource_array[idx]) { - /** - */ - widget_send_updated_by_idx(info->handle, idx); break; } } if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) { - /* Send updated event for PRIMARY BUFFER */ - if (front_resource_id == widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER)) { - widget_send_updated_by_idx(info->handle, WIDGET_PRIMARY_BUFFER); - } else { - DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER)); + idx = WIDGET_PRIMARY_BUFFER; + } + + /* Send updated event for PRIMARY BUFFER */ + if (front_resource_id == widget_viewer_get_resource_id(info->handle, idx)) { + if (info->ctrl_mode.dump_to_file) { + char fname[512]; + void *canvas; + + snprintf(fname, sizeof(fname) - 1, "/tmp/%s.%u.%lf.raw", widget_util_basename(info->id), front_resource_id, ecore_time_get()); + canvas = widget_provider_buffer_dump_frame(info->handle, idx); + if (canvas) { + int w, h; + int size; + + ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h); + size = w * h * sizeof(int); + + dump_to_file(canvas, size, fname); + free(canvas); + } } + widget_send_updated_by_idx(info->handle, idx); + } else { + DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, widget_viewer_get_resource_id(info->handle, idx)); + } + } else { + if (WIDGET_CONF_PREMULTIPLIED_COLOR) { + void *canvas; + int w, h; + + // Get a pointer of a buffer of the virtual canvas + canvas = (void *)ecore_evas_buffer_pixels_get(info->ee); + if (!canvas) { + ErrPrint("Failed to get pixel canvas\n"); + return; + } + + ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h); + evas_data_argb_unpremul(canvas, w * h); + } + + if (info->ctrl_mode.dump_to_file) { + void *canvas; + char fname[512]; + int size; + int w, h; + + canvas = (void *)ecore_evas_buffer_pixels_get(info->ee); + if (!canvas) { + ErrPrint("Failed to get pixel canvas\n"); + return; + } + + /** + * TODO + * Save to a file + */ + ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h); + size = w * h * sizeof(int); + + snprintf(fname, sizeof(fname) - 1, "/tmp/%s.%lf.raw", widget_util_basename(info->id), ecore_time_get()); + dump_to_file(canvas, size, fname); + } + + if (info->type == VWIN_GEM) { + widget_buffer_post_render(info->handle); + } else if (info->type == VWIN_SW_BUF) { + widget_viewer_sync_buffer(info->handle); } - } else if (info->type == VWIN_SW_BUF) { - widget_viewer_sync_buffer(info->handle); } } +static int pre_ctrl_mode_cb(const char *id, void *data) +{ + vwin_info_t info = data; + const char *path; + int cmd; + int value; + + /* Try provider_app first */ + if (!info || info->state != VWIN_INFO_CREATED || !id || !info->id) { + return WIDGET_ERROR_INVALID_PARAMETER; + } + + path = widget_util_uri_to_path(id); + if (path && strcmp(info->id, path)) { + /* Skip */ + DbgPrint("SKIP: Pre orientation event callback is called [%s], %s\n", id, info->id); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + widget_get_last_ctrl_mode(path, &cmd, &value); + + if (cmd == WIDGET_CTRL_MODE_DUMP_FRAME) { + info->ctrl_mode.dump_to_file = !!value; + DbgPrint("CtrlMode: DumpToFile: %d\n", info->ctrl_mode.dump_to_file); + } + + return WIDGET_ERROR_NONE; +} + static int pre_orientation_cb(const char *id, void *data) { vwin_info_t info = data; @@ -658,7 +901,7 @@ static int pre_orientation_cb(const char *id, void *data) int orientation; /* Try provider_app first */ - if (!info || info->state != VWIN_INFO_CREATED || !id) { + if (!info || info->state != VWIN_INFO_CREATED || !id || !info->id) { return WIDGET_ERROR_INVALID_PARAMETER; } @@ -719,14 +962,27 @@ static void ecore_evas_free_cb(Ecore_Evas *ee) return; } + if (info->pended_events_consumer) { + widget_buffer_event_data_t event_info; + + DbgPrint("Clearing pended event consumer\n"); + ecore_timer_del(info->pended_events_consumer); + info->pended_events_consumer = NULL; + + EINA_LIST_FREE(info->pended_events_list, event_info) { + free(event_info); + } + } + widget_del_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info); + widget_del_pre_callback(WIDGET_PRE_CTRL_MODE_CALLBACK, pre_ctrl_mode_cb, info); if (info->e) { evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb); evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb); } - info->deleted = 1; + info->flags.field.deleted = 1; info->ee = NULL; } @@ -767,15 +1023,15 @@ PUBLIC Evas *widget_get_evas(const char *id) } #ifdef WIDGET_FEATURE_GBAR_SUPPORTED - info->is_gbar = is_gbar; + info->flags.field.is_gbar = is_gbar; #else - info->is_gbar = 0; + info->flags.field.is_gbar = 0; #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */ /** * Acquire a buffer for canvas. */ - info->handle = widget_create_buffer(info->id, info->is_gbar, + info->handle = widget_create_buffer(info->id, info->flags.field.is_gbar, binder_widget_auto_align(), event_handler_cb, info); @@ -830,6 +1086,7 @@ PUBLIC Evas *widget_get_evas(const char *id) widget_add_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info); widget_add_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, pre_orientation_cb, info); + widget_add_pre_callback(WIDGET_PRE_CTRL_MODE_CALLBACK, pre_ctrl_mode_cb, info); orientation = widget_get_orientation(info->id); if (orientation < 0) {