X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fvirtual_window.c;h=1d918782aaeae3e5837f729c1b192e81f86ff829;hb=888ee28916d99ce45d4916815dd666a62451f7da;hp=74d1b05705e5ab11ba07f89832b21c680e9b4373;hpb=18c34b2f3a6e6cf139d1e71196914e6e45fcad28;p=apps%2Fnative%2Fwidget%2Fwidget.git diff --git a/src/virtual_window.c b/src/virtual_window.c index 74d1b05..1d91878 100644 --- a/src/virtual_window.c +++ b/src/virtual_window.c @@ -23,6 +23,11 @@ #include #include #include +#include +#include +#include +#include +#include #include @@ -33,54 +38,41 @@ #include #include #include +#include +#include +#include #include "widget.h" #include "widget_internal.h" #include "debug.h" +#include "binder.h" #define IS_GBAR 1 #define PUBLIC __attribute__((visibility("default"))) #define WIDGET_WIN_TAG "dynamic,box,win" +#define WIN_INFO_TAG "dynamic,box,info" #define WIDGET_DEFAULT_WIDTH 1 #define WIDGET_DEFAULT_HEIGHT 1 -#define GL_ENGINE "opengl_x11" - -static struct static_info { - Ecore_Evas *(*alloc_canvas)(int w, int h, void *(*a)(void *data, int size), void (*f)(void *data, void *ptr), void *data); - Ecore_Evas *(*alloc_canvas_with_stride)(int w, int h, void *(*a)(void *data, int size, int *stride, int *bpp), void (*f)(void *data, void *ptr), void *data); - Ecore_Evas *(*alloc_canvas_with_pixmap)(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h, Ecore_X_Pixmap (*alloc_cb)(void *data, Ecore_X_Window parent, int w, int h, int depth), void (*free_cb)(void *data, Ecore_X_Pixmap pixmap), void *data); -} s_info = { - .alloc_canvas = NULL, - .alloc_canvas_with_stride = NULL, - .alloc_canvas_with_pixmap = NULL, -}; + +#define MOUSE_BUTTON_LEFT 1 /** - * @brief - * Abstracted Data Type of Virtual Window + * @note + * Supported touch devices are limited to 32. + * Because of count of bits of integer type. (32 bits) */ -typedef struct virtual_window_info { - char *id; /**< Identification */ - widget_buffer_h handle; /**< Livebox buffer handle */ - enum win_type { - VWIN_SW_BUF = 0x00, /**< S/W buffer */ - VWIN_GEM = 0x01, /**< GEM buffer */ - VWIN_PIXMAP = 0x02, /**< PIXMAP */ - VWIN_ERROR = 0x03 /**< Unknown */ - } type; - Ecore_Evas *ee; - Evas *e; - int is_gbar; - int deleted; - int w; - int h; - unsigned int *resource_array; - int resource_cnt; - - int pressed; -} *vwin_info_t; +#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) { @@ -93,62 +85,58 @@ static inline Evas_Object *get_highlighted_object(Evas_Object *obj) return ho; } -/** - * @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 void apply_orientation(int degree, int *x, int *y, int width, int height, input_event_source_e source) { - 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; + int _x; + int _y; + int _angle; - if (!info->handle) { - /* Just ignore this event */ - return 0; + if (source == INPUT_EVENT_SOURCE_VIEWER) { + /* Already rotated */ + return; } - 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: %s\n", strerror(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; - } - } - } + _x = *x; + _y = *y; + switch (degree) { + case 0: + return; + case 90: + *x = _y; + *y = width - _x; + return; + case 180: + *x = width - _x; + *y = height - _y; + return; + case 270: + *x = height - _y; + *y = _x; + return; + default: /** - * 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 + * @FIXME + * This rotation formular is not work correctly. + * The pointer should be rotated by other way. + * This is not what we want. */ - 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; - } - } + _angle = degree; - timestamp = event_info->timestamp * 1000.0f; + *x = (double)_x * cos((double)_angle) - (double)_y * sin((double)_angle); + *y = (double)_x * sin((double)_angle) + (double)_y * cos((double)_angle); + return; } +} +static inline int processing_events(vwin_info_t info, widget_buffer_event_data_t event_info, double timestamp) +{ + Elm_Access_Action_Info action_info; + Elm_Access_Action_Type action_type; + Evas_Object *parent_elm; + KeySym *key_symbol; + unsigned int flags = 0; + int ret = 0; /** * @note * Feed up events @@ -159,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); @@ -169,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); @@ -182,11 +176,23 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ evas_event_feed_mouse_out(info->e, timestamp, NULL); break; case WIDGET_BUFFER_EVENT_DOWN: - if (info->pressed) { + apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source); + + 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); + } } /** @@ -194,38 +200,78 @@ 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); /** * @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: - 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; + apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source); + + 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); @@ -234,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 @@ -262,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; @@ -274,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; @@ -286,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; @@ -297,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; @@ -308,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; @@ -319,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; @@ -333,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; @@ -347,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; @@ -361,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; @@ -372,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; @@ -386,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; @@ -400,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; @@ -414,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; @@ -428,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; @@ -442,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; @@ -456,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; @@ -555,242 +601,130 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ return ret; } -/** - * @note - * This callback can be called twice (or more) to get a several pixmaps - * Acquired pixmaps are used for double/tripple buffering for canvas - */ -static Ecore_X_Pixmap alloc_pixmap_cb(void *data, Ecore_X_Window parent, int w, int h, int depth) +static Eina_Bool pended_event_consumer_cb(void *data) { vwin_info_t info = data; - Ecore_X_Pixmap pixmap; + widget_buffer_event_data_t event_info; - if (!info->handle) { - ErrPrint("Invalid handle\n"); - return 0u; + event_info = eina_list_nth(info->pended_events_list, 0); + if (!event_info) { + info->pended_events_consumer = NULL; + return ECORE_CALLBACK_CANCEL; } - info->w = w; - info->h = h; - DbgPrint("Size of ee is updated: %dx%d - %d (info: %p)\n", info->w, info->h, depth, info); - depth >>= 3; - - if (widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER) == 0u) { - /** - * @note - * Need to allocate a primary buffer - */ - widget_viewer_acquire_buffer(info->handle, WIDGET_PRIMARY_BUFFER, info->w, info->h, depth); - if (!info->handle) { - ErrPrint("Failed to get the buffer\n"); - return 0u; - } - - pixmap = (Ecore_X_Pixmap)widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER); - } else if (WIDGET_CONF_EXTRA_BUFFER_COUNT > 0) { - int idx; - - if (!info->resource_array) { - info->resource_array = calloc(WIDGET_CONF_EXTRA_BUFFER_COUNT, sizeof(*info->resource_array)); - if (!info->resource_array) { - ErrPrint("Out of memory: %s\n", strerror(errno)); - return 0u; - } - - idx = 0; - } else { - for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) { - if (info->resource_array[idx] == 0u) { - break; - } - } - - if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) { - ErrPrint("Out of index: %d\n", idx); - return 0u; - } - } - - if (widget_viewer_acquire_buffer(info->handle, idx, info->w, info->h, depth) < 0) { - ErrPrint("Failed to acquire a buffer for %d\n", idx); - return 0u; - } - - info->resource_array[idx] = widget_viewer_get_resource_id(info->handle, idx); - if (info->resource_array[idx] == 0u) { - ErrPrint("Failed to allocate pixmap\n"); - } + DbgPrint("Consuming delayed events\n"); + (void)processing_events(info, event_info, event_info->timestamp); - DbgPrint("Allocated index: %d/%d - %u\n", idx, WIDGET_CONF_EXTRA_BUFFER_COUNT, info->resource_array[idx]); - pixmap = info->resource_array[idx]; - } else { - ErrPrint("Unable to allocate pixmap\n"); - pixmap = 0u; - } - - /** - * Acquire a buffer for canvas. - */ - info->type = VWIN_PIXMAP; - info->resource_cnt += !!(unsigned int)pixmap; - return pixmap; + info->pended_events_list = eina_list_remove(info->pended_events_list, event_info); + free(event_info); + return ECORE_CALLBACK_RENEW; } -static void free_pixmap_cb(void *data, Ecore_X_Pixmap pixmap) +/** + * @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; - if (!info->handle) { - return; - } + /** + * @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->type != VWIN_PIXMAP) { - ErrPrint("Impossible\n"); + if (!info || info->state != VWIN_INFO_CREATED || !info->handle || info->flags.field.deleted) { + /* Just ignore this event */ + return 0; } - if (widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER) == pixmap) { - if (widget_viewer_release_buffer(info->handle, WIDGET_PRIMARY_BUFFER) < 0) { - DbgPrint("Failed to release buffer\n"); - } - info->resource_cnt--; - } else { - int idx; - - for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) { - /** - * @note - * Find a index to release it - */ - if (info->resource_array[idx] == pixmap) { - if (widget_viewer_release_buffer(info->handle, idx) < 0) { - DbgPrint("Failed to release buffer\n"); - } - info->resource_array[idx] = 0u; - info->resource_cnt--; - break; + 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"); } } - } - - if (info->deleted && info->resource_cnt == 0) { - DbgPrint("Destroy buffer handle\n"); - - widget_destroy_buffer(info->handle); - free(info->resource_array); - free(info->id); - free(info); - } -} -static void *alloc_fb(void *data, int size) -{ - vwin_info_t info = data; - void *buffer; - - if (info->ee) { - ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h); - DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info); + return 0; } - if (!info->handle) { - ErrPrint("Failed to create a buffer\n"); - return NULL; - } + 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 (widget_viewer_acquire_buffer(info->handle, WIDGET_PRIMARY_BUFFER, info->w, info->h, sizeof(int)) < 0) { - ErrPrint("Failed to acquire buffer\n"); - return NULL; - } + 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 it supports the H/W accelerated buffer, - * Use it. - */ - if (widget_support_hw_buffer(info->handle)) { - if (widget_create_hw_buffer(info->handle) == 0) { - buffer = widget_buffer_hw_buffer(info->handle); - if (buffer) { - DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h); - info->type = VWIN_GEM; - return buffer; + if (timestamp > WIDGET_CONF_EVENT_FILTER) { + DbgPrint("Dropped %lf\n", timestamp); + return 0; + } } } - ErrPrint("Failed to allocate HW Accelerated buffer\n"); - } - - /** - * Or use the buffer of a S/W backend. - */ - buffer = widget_ref_buffer(info->handle); - DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h); - info->type = VWIN_SW_BUF; - return buffer; -} - -static void *alloc_stride_fb(void *data, int size, int *stride, int *bpp) -{ - void *buffer; - - buffer = alloc_fb(data, size); - if (buffer) { - vwin_info_t info = data; - int _stride; + /** + * 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(); - *bpp = sizeof(int); - _stride = widget_buffer_stride(info->handle); - if (_stride < 0) { - _stride = info->w * *bpp; + timestamp -= event_info->timestamp; + if (timestamp > WIDGET_CONF_EVENT_FILTER) { + DbgPrint("Dropped %lf\n", timestamp); + return 0; + } } - *stride = _stride; - *bpp <<= 3; - DbgPrint("bpp: %d, stride: %d\n", *bpp, *stride); - } - - return buffer; -} - -static void free_fb(void *data, void *ptr) -{ - vwin_info_t info = data; - - if (!info->handle) { - return; + timestamp = event_info->timestamp * 1000.0f; } - if (info->type == VWIN_GEM) { - if (widget_destroy_hw_buffer(info->handle) == 0) { - DbgPrint("HW Accelerated buffer is destroyed\n"); + 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); } - } else if (info->type == VWIN_SW_BUF) { - DbgPrint("SW buffer is destroyed, %p\n", info); - widget_unref_buffer(ptr); - } else if (info->type == VWIN_PIXMAP) { - ErrPrint("Unable to reach to here\n"); - } - - if (widget_viewer_release_buffer(info->handle, WIDGET_PRIMARY_BUFFER) < 0) { - ErrPrint("Failed to release buffer\n"); } - if (info->deleted) { - widget_destroy_buffer(info->handle); - free(info->resource_array); - free(info->id); - free(info); - } + return processing_events(info, event_info, timestamp); } static void pre_render_cb(void *data, Evas *e, void *event_info) { vwin_info_t info = data; - if (!info->handle) { + if (!info || info->state != VWIN_INFO_CREATED || !info->handle) { return; } - if (widget_conf_premultiplied_alpha()) { + if (WIDGET_CONF_PREMULTIPLIED_COLOR) { Evas_Coord w; Evas_Coord h; @@ -809,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->handle) { + 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; @@ -842,60 +787,202 @@ 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 void pre_destroy_cb(widget_pre_callback_e type, const char *pkgname, const char *id, void *data) +static int pre_ctrl_mode_cb(const char *id, void *data) { vwin_info_t info = data; - if (strcmp(info->id, id)) { + 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 destroy event callback is called [%s]\n", id); - return; + 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; + const char *path; + int orientation; + + /* 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; + } + + DbgPrint("Pre orientation event callback is called [%s]\n", id); + orientation = widget_get_orientation(path); + if (orientation < 0) { + ErrPrint("Failed to get orientation: %X\n", orientation); + } else { + info->orientation = orientation; + } + + return WIDGET_ERROR_NONE; +} + +static int pre_destroy_cb(const char *id, void *data) +{ + vwin_info_t info = data; + const char *path = NULL; + + if (!info || info->state != VWIN_INFO_CREATED) { + return WIDGET_ERROR_INVALID_PARAMETER; + } + + if (id) { + path = widget_util_uri_to_path(id); + + if (path && strcmp(info->id, path)) { + /* Skip */ + DbgPrint("SKIP: Pre destroy event callback is called [%s], %s\n", id, info->id); + return WIDGET_ERROR_INVALID_PARAMETER; + } } + DbgPrint("Pre destroy event callback is called [%s]\n", id); if (info->ee) { DbgPrint("Toggle manual render mode to prevent from unwanted rendering"); ecore_evas_manual_render_set(info->ee, EINA_TRUE); } + + return WIDGET_ERROR_NONE; } static void ecore_evas_free_cb(Ecore_Evas *ee) { vwin_info_t info; - info = ecore_evas_data_get(ee, "dynamic,box,info"); + info = ecore_evas_data_get(ee, WIN_INFO_TAG); if (!info) { DbgPrint("Info is not valid\n"); return; } - widget_provider_del_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info); + 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; } @@ -906,8 +993,7 @@ PUBLIC Evas *widget_get_evas(const char *id) #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */ { vwin_info_t info; - Evas_Object *rect; - const char *engine; + int orientation; /** * @TODO @@ -915,28 +1001,6 @@ PUBLIC Evas *widget_get_evas(const char *id) * this function should returns ERROR. */ - if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride && !s_info.alloc_canvas_with_pixmap) { - s_info.alloc_canvas_with_pixmap = dlsym(RTLD_DEFAULT, "ecore_evas_gl_x11_pixmap_allocfunc_new"); - if (!s_info.alloc_canvas_with_pixmap) { - DbgPrint("pixmap_allocfunc_new is not found\n"); - } - - s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new"); - if (!s_info.alloc_canvas_with_stride) { - DbgPrint("allocfunc_with_stirde_new is not found\n"); - } - - s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new"); - if (!s_info.alloc_canvas) { - ErrPrint("allocfunc_new is not found\n"); - } - - if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas && !s_info.alloc_canvas_with_pixmap) { - ErrPrint("No way to allocate canvas\n"); - return NULL; - } - } - if (!id) { ErrPrint("Invalid parameter\n"); return NULL; @@ -944,32 +1008,36 @@ PUBLIC Evas *widget_get_evas(const char *id) info = calloc(1, sizeof(*info)); if (!info) { - ErrPrint("Heap: %s\n", strerror(errno)); + ErrPrint("Heap: %d\n", errno); return NULL; } + info->state = VWIN_INFO_CREATED; + info->id = strdup(id); if (!info->id) { - ErrPrint("Heap: %s\n", strerror(errno)); + ErrPrint("Heap: %d\n", errno); + info->state = VWIN_INFO_DESTROYED; free(info); return NULL; } #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, - (widget_conf_auto_align() || !s_info.alloc_canvas_with_stride), + info->handle = widget_create_buffer(info->id, info->flags.field.is_gbar, + binder_widget_auto_align(), event_handler_cb, info); if (!info->handle) { ErrPrint("Failed to create a widget buffer\n"); + info->state = VWIN_INFO_DESTROYED; free(info->id); free(info); return NULL; @@ -981,34 +1049,17 @@ PUBLIC Evas *widget_get_evas(const char *id) info->w = WIDGET_DEFAULT_WIDTH; info->h = WIDGET_DEFAULT_HEIGHT; - engine = elm_config_preferred_engine_get(); - DbgPrint("Preferred engine: %s (%s)\n", engine, GL_ENGINE); - if (engine && !strcmp(engine, GL_ENGINE)) { - if (s_info.alloc_canvas_with_pixmap) { - info->ee = s_info.alloc_canvas_with_pixmap(NULL, 0u, 0, 0, info->w, info->h, alloc_pixmap_cb, free_pixmap_cb, info); - if (!info->ee) { - ErrPrint("Unable to create a ee for pixmap\n"); - } - } - } - - if (!info->ee) { - if (!widget_conf_auto_align() && s_info.alloc_canvas_with_stride) { - info->ee = s_info.alloc_canvas_with_stride(info->w, info->h, alloc_stride_fb, free_fb, info); - } else if (s_info.alloc_canvas) { - info->ee = s_info.alloc_canvas(info->w, info->h, alloc_fb, free_fb, info); - } - } - + info->ee = binder_ecore_evas_new(info); if (!info->ee) { ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h); widget_destroy_buffer(info->handle); + info->state = VWIN_INFO_DESTROYED; free(info->id); free(info); return NULL; } - ecore_evas_data_set(info->ee, "dynamic,box,info", info); + ecore_evas_data_set(info->ee, WIN_INFO_TAG, info); /** * @note @@ -1033,7 +1084,16 @@ PUBLIC Evas *widget_get_evas(const char *id) evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info); evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info); - widget_provider_add_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info); + 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) { + ErrPrint("Failed to get orientation[%s]: %X\n", info->id, orientation); + } else { + info->orientation = orientation; + } return info->e; }