Sync with the latest tizen 2.4
[apps/native/widget/widget.git] / src / virtual_window.c
index e1b4ca1..301f427 100644 (file)
@@ -105,62 +105,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
@@ -568,7 +520,121 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_
                break;
        }
 
-       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->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;
+       }
+
+       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)
@@ -719,6 +785,18 @@ 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);
 
        if (info->e) {