[elm_webview]fix some buggy codes
[framework/uifw/elementary.git] / src / lib / els_webview.c
1 /*
2  *
3  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
4  */
5 #include <Elementary.h>
6 #include "elm_priv.h"
7
8 #ifdef ELM_EWEBKIT
9 #include <glib.h>
10 #include <glib-object.h>
11 #include <EWebKit.h>
12 #include <cairo.h>
13
14 #define SMART_NAME "els_webview"
15 #define API_ENTRY Smart_Data *sd; sd = evas_object_smart_data_get(obj); if ((!obj) || (!sd) || (evas_object_type_get(obj) && strcmp(evas_object_type_get(obj), SMART_NAME)))
16 #define INTERNAL_ENTRY Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
17 #define EWK_VIEW_PRIV_GET_OR_RETURN(sd, ptr, ...)                   \
18    Ewk_View_Private_Data* ptr = ((Ewk_View_Smart_Data*)sd)->_priv; \
19    if (!ptr) \
20    {                                                     \
21       ERR("no private data for object %p (%s)",               \
22          ((Ewk_View_Smart_Data*)sd)->self,                           \
23          evas_object_type_get(((Ewk_View_Smart_Data*)sd)->self));    \
24       return __VA_ARGS__;                                         \
25    }
26
27 #define EWEBKIT_PATH "/usr/lib/libewebkit.so"
28 #define CAIRO_PATH "/usr/lib/libcairo.so.2"
29
30 #define MINIMAP_WIDTH 120
31 #define MINIMAP_HEIGHT 200
32 #define MAX_TUC 1024*1024*10
33 #define MAX_URI 512
34 #define MOBILE_DEFAULT_WIDTH 320
35
36 #define WEBVIEW_EDJ "/usr/share/edje/ewebview.edj"
37 #define WEBKIT_EDJ "/usr/share/edje/webkit.edj"
38 #define WEBVIEW_THEME_EDJ "/usr/share/edje/ewebview-theme.edj"
39
40 #define DEFAULT_LAYOUT_WIDTH 1024
41 #define MIN_ZOOM_RATIO 0.09f
42 #define MAX_ZOOM_RATIO 4.0f
43
44 #define NEED_TO_REMOVE
45
46 typedef struct _Smart_Data Smart_Data;
47
48 struct _Smart_Data {
49      Ewk_View_Smart_Data base; //default data
50
51      Evas_Object* widget;
52      int locked_dx;
53      int locked_dy;
54
55      /* ewk functions */
56      void (*ewk_view_theme_set)(Evas_Object *, const char *);
57      Evas_Object *(*ewk_view_frame_main_get)(const Evas_Object *);
58      Eina_Bool (*ewk_view_uri_set)(Evas_Object *, const char *);
59      float (*ewk_view_zoom_get)(const Evas_Object *);
60      Eina_Bool (*ewk_view_zoom_set)(Evas_Object *, float, Evas_Coord, Evas_Coord);
61      Eina_Bool (*ewk_view_zoom_weak_set)(Evas_Object *, float, Evas_Coord, Evas_Coord);
62      Eina_Bool (*ewk_view_zoom_text_only_set)(Evas_Object *, Eina_Bool);
63      Eina_Bool (*ewk_view_zoom_cairo_scaling_get)(const Evas_Object *);
64      Eina_Bool (*ewk_view_zoom_cairo_scaling_set)(Evas_Object *, Eina_Bool);
65      void (*ewk_view_viewport_get)(Evas_Object *, int *, int *, float *, float *, float *, Eina_Bool *);
66      void (*ewk_view_zoom_range_set)(Evas_Object *, float, float);
67      void (*ewk_view_user_scalable_set)(Evas_Object *, Eina_Bool);
68      Eina_Bool (*ewk_view_pre_render_region)(Evas_Object *, Evas_Coord, Evas_Coord, Evas_Coord, Evas_Coord, float);
69      void (*ewk_view_pre_render_cancel)(Evas_Object *);
70      Eina_Bool (*ewk_view_enable_render)(const Evas_Object *);
71      Eina_Bool (*ewk_view_disable_render)(const Evas_Object *);
72      void (*ewk_view_fixed_layout_size_set)(Evas_Object *, Evas_Coord, Evas_Coord);
73      Eina_Bool (*ewk_view_setting_enable_plugins_get)(const Evas_Object *);
74      void (*ewk_view_pause_and_or_hide_plugins)(Evas_Object *, Eina_Bool, Eina_Bool);
75      Eina_Bool (*ewk_view_suspend_request)(Evas_Object *);
76      Eina_Bool (*ewk_view_resume_request)(Evas_Object *);
77      Eina_Bool (*ewk_view_select_none)(Evas_Object *);
78      Eina_Bool (*ewk_view_get_smart_zoom_rect)(Evas_Object *, int, int, const Evas_Event_Mouse_Up *, Eina_Rectangle *);
79      Eina_Bool (*ewk_view_paint_contents)(Ewk_View_Private_Data *, cairo_t *, const Eina_Rectangle *);
80      Eina_Bool (*ewk_view_stop)(Evas_Object *);
81      Ewk_Tile_Unused_Cache *(*ewk_view_tiled_unused_cache_get)(const Evas_Object *);
82      void (*ewk_view_tiled_unused_cache_set)(Evas_Object *, Ewk_Tile_Unused_Cache *);
83      void (*ewk_tile_unused_cache_max_set)(Ewk_Tile_Unused_Cache *, size_t);
84      size_t (*ewk_tile_unused_cache_max_get)(const Ewk_Tile_Unused_Cache *);
85      size_t (*ewk_tile_unused_cache_used_get)(const Ewk_Tile_Unused_Cache *);
86      void (*ewk_tile_unused_cache_auto_flush)(Ewk_Tile_Unused_Cache *);
87      char * (*ewk_page_check_point_for_keyboard)(Evas_Object *, int, int, Eina_Bool *);
88      Eina_Bool (*ewk_page_check_point)(Evas_Object *, int, int, Evas_Event_Mouse_Down *, Eina_Bool *, Eina_Bool *, char **, char **, char **);
89      char ** (*ewk_page_dropdown_get_options)(Evas_Object *, int, int, int *, int *);
90      Eina_Bool (*ewk_page_dropdown_set_current_index)(Evas_Object *, int, int, int);
91      Eina_Bool (*ewk_frame_contents_size_get)(const Evas_Object *, Evas_Coord *, Evas_Coord *);
92      Ewk_Hit_Test * (*ewk_frame_hit_test_new)(const Evas_Object *, int, int);
93      Eina_Bool (*ewk_frame_feed_mouse_down)(Evas_Object *, const Evas_Event_Mouse_Down *);
94      Eina_Bool (*ewk_frame_feed_mouse_up)(Evas_Object *, const Evas_Event_Mouse_Up *);
95      Eina_Bool (*ewk_frame_visible_content_geometry_get)(const Evas_Object *, Eina_Bool, int *, int *, int *, int *);
96      Eina_Bool (*ewk_frame_scroll_pos_get)(const Evas_Object *, int *, int *);
97      Evas_Object * (*ewk_frame_view_get)(const Evas_Object *);
98      void (*ewk_frame_hit_test_free)(Ewk_Hit_Test *);
99      Eina_Bool (*ewk_frame_contents_set)(Evas_Object *, const char *, size_t, const char *, const char *, const char *);
100      Eina_Bool (*ewk_frame_select_closest_word)(Evas_Object *, int, int, int *, int *, int *, int *, int *, int *);
101      Eina_Bool (*ewk_frame_selection_handlers_get)(Evas_Object *, int *, int *, int *, int *, int *, int *);
102      Eina_Bool (*ewk_frame_selection_left_set)(Evas_Object *, int, int, int *, int *, int *);
103      Eina_Bool (*ewk_frame_selection_right_set)(Evas_Object *, int, int, int *, int *, int *);
104      Eina_Bool (*ewk_frame_feed_focus_in)(Evas_Object *);
105      Eina_Bool (*ewk_frame_scroll_add)(Evas_Object *, int, int);
106
107      /* cairo functions */
108      cairo_t * (*cairo_create)(cairo_surface_t *);
109      void (*cairo_destroy)(cairo_t *);
110      void (*cairo_paint)(cairo_t *);
111      void (*cairo_stroke)(cairo_t *cr); 
112      void (*cairo_scale)(cairo_t *, double, double);
113      void (*cairo_rectangle)(cairo_t *, double, double, double, double);
114      void (*cairo_set_source_rgb)(cairo_t *, double, double, double);
115      cairo_status_t (*cairo_surface_status)(cairo_surface_t *);
116      void (*cairo_surface_destroy)(cairo_surface_t *);
117      void (*cairo_set_line_width)(cairo_t *, double);
118      void (*cairo_set_source_surface)(cairo_t *, cairo_surface_t *, double, double);
119      cairo_status_t (*cairo_surface_write_to_png)(cairo_surface_t *, const char *);
120      cairo_surface_t * (*cairo_image_surface_create)(cairo_format_t, int, int);
121      void (*cairo_set_antialias)(cairo_t *, cairo_antialias_t);
122      cairo_surface_t * (*cairo_image_surface_create_for_data)(unsigned char *, cairo_format_t, int, int, int);
123
124      /* add user data */
125      struct {
126           Evas_Object* eo;
127           Evas_Object* content;
128           int cw, ch;
129      } minimap;
130
131      struct {
132           char** options;
133           int option_cnt;
134           int option_idx;
135      } dropdown;
136
137      struct {
138           Evas_Point basis;    // basis point of zoom
139           int finger_distance; // distance between two finger
140           int zooming_level;
141           float zooming_rate;
142           float zoom_rate_at_start;
143           float zoom_rate_to_set;
144           Evas_Point scroll_at_start;
145           Evas_Point scroll_to_set;
146           float init_zoom_rate;
147           float min_zoom_rate; //content based minimum
148           float max_zoom_rate;
149           Eina_Bool scalable;
150      } zoom;
151
152      struct {
153           int w, h;
154      } content;
155
156      struct {
157           int default_w;
158           int w, h;
159      } layout;
160
161      Eina_Bool auto_fitting;
162      Ecore_Animator* smart_zoom_animator;
163
164      Evas_Point pan_s;
165      Evas_Event_Mouse_Down mouse_down_copy;
166      Evas_Event_Mouse_Up mouse_up_copy;
167
168      cairo_surface_t* thumbnail;
169      Ecore_Animator* animator;
170      int hold_counter;
171      float current_zoom_level;
172
173      Eina_Bool tiled;
174      Eina_Bool events_feed;
175      Eina_Bool event_blocked;
176      Eina_Bool event_only;
177      Eina_Bool on_panning;
178      Eina_Bool on_zooming;
179      Eina_Bool is_mobile_page;
180
181      Eina_Bool text_selection_on;
182      struct {
183           Evas_Coord_Rectangle front;
184           Evas_Coord_Rectangle back;
185           Evas_Point front_handle;
186           Evas_Point back_handle;
187           Eina_Bool front_handle_moving;
188           Eina_Bool back_handle_moving;
189      } text_selection;
190      void* touch_obj;
191 };
192
193 /* local subsystem functions */
194 static void      _smart_show(Evas_Object* obj);
195 static void      _smart_hide(Evas_Object* obj);
196 static void      _smart_resize(Evas_Object* obj, Evas_Coord w, Evas_Coord h);
197 static void      _smart_move(Evas_Object* obj, Evas_Coord x, Evas_Coord y);
198 static void      _smart_calculate(Evas_Object* obj);
199 static Eina_Bool _smart_mouse_down(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Down* ev);
200 static Eina_Bool _smart_mouse_up(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Up* ev);
201 static Eina_Bool _smart_mouse_move(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Move* ev);
202 static void      _view_on_mouse_down(void* data, Evas* e, Evas_Object* o, void* event_info);
203 static void      _view_on_mouse_up(void* data, Evas* e, Evas_Object* o, void* event_info);
204 static void      _smart_load_started(void* data, Evas_Object* webview, void* error);
205 static void      _smart_load_finished(void* data, Evas_Object* webview, void* arg);
206 static void      _smart_load_error(void* data, Evas_Object* webview, void* arg);
207 static void      _smart_viewport_changed(void* data, Evas_Object* webview, void* arg);
208 static void      _smart_contents_size_changed(void* data, Evas_Object* frame, void* arg);
209 static void      _smart_load_nonemptylayout_finished(void* data, Evas_Object* frame, void* arg);
210 static void      _smart_cb_view_created(void* data, Evas_Object* webview, void* arg);
211 static void      _smart_add(Evas_Object* obj);
212 static void      _smart_del(Evas_Object* o);
213 static void      _directional_pre_render(Evas_Object* webview, int dx, int dy);
214 static void      _smart_cb_mouse_down(void* data, Evas_Object* webview, void* ev);
215 static void      _smart_cb_mouse_up(void* data, Evas_Object* webview, void* ev);
216 static void      _smart_cb_mouse_tap(void* data, Evas_Object* webview, void* ev);
217 static void      _smart_cb_pan_start(void* data, Evas_Object* webview, void* ev);
218 static void      _smart_cb_pan_by(void* data, Evas_Object* webview, void* ev);
219 static void      _smart_cb_pan_stop(void* data, Evas_Object* webview, void* ev);
220 static void      _smart_cb_select_closest_word(void* data, Evas_Object* webview, void* ev);
221 static void      _smart_cb_unselect_closest_word(void* data, Evas_Object* webview, void* ev);
222 static void      _suspend_all(Smart_Data *sd);
223 static void      _resume_all(Smart_Data *sd);
224 static void      _zoom_start(Smart_Data* sd, int centerX, int centerY, int distance);
225 static void      _zoom_move(Smart_Data* sd, int centerX, int centerY, int distance);
226 static void      _zoom_stop(Smart_Data* sd);
227 static void      _adjust_to_contents_boundary(Evas_Object* webview, int* to_x, int* to_y, int from_x, int from_y, float new_zoom_rate);
228 static int       _smart_zoom_animator(void* data);
229 static void      _smart_cb_pinch_zoom_start(void* data, Evas_Object* webview, void* event_info);
230 static void      _smart_cb_pinch_zoom_move(void* data, Evas_Object* webview, void* event_info);
231 static void      _smart_cb_pinch_zoom_stop(void* data, Evas_Object* webview, void* event_info);
232 static void      _smart_cb_vertical_zoom_start(void* data, Evas_Object* webview, void* event_info);
233 static void      _smart_cb_vertical_zoom_move(void* data, Evas_Object* webview, void* event_info);
234 static void      _smart_cb_vertical_zoom_stop(void* data, Evas_Object* webview, void* event_info);
235 static void      _smart_cb_smart_zoom(void* data, Evas_Object* webview, void* event_info);
236 static void      _zoom_to_rect(Smart_Data *sd, int x, int y);
237 static void      _text_selection_init(Evas_Object* parent);
238 static void      _text_selection_show(void);
239 static void      _text_selection_hide(Smart_Data *sd);
240 static void      _text_selection_set_front_info(Smart_Data *sd, int x, int y, int height);
241 static void      _text_selection_set_back_info(Smart_Data *sd, int x, int y, int height);
242 static Eina_Bool _text_selection_handle_pressed(Smart_Data *sd, int x, int y);
243 static void      _text_selection_update_position(Smart_Data *sd, int x, int y);
244 static void      _text_selection_move_by(Smart_Data *sd, int dx, int dy);
245 static void      _minimap_update_detail(Evas_Object* minimap, Smart_Data *sd, cairo_surface_t* src, int srcW, int srcH, Eina_Rectangle* visibleRect);
246 static void      _minimap_update(Evas_Object* minimap, Smart_Data *sd, cairo_surface_t* src, int minimapW, int minimapH);
247 static cairo_surface_t* _image_clone_get(Smart_Data *sd, int* minimap_w, int* minimap_h);
248 static void      _unzoom_position(Evas_Object* webview, int x, int y, int* ux, int* uy);
249 static void      _coords_evas_to_ewk(Evas_Object* webview, int x, int y, int* ux, int* uy);
250 static void      _coords_ewk_to_evas(Evas_Object* webview, int x, int y, int* ux, int* uy);
251
252 /* local subsystem globals */
253 static Evas_Smart *_smart = NULL;
254 static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL;
255
256 /* ewk functions */
257 static void *ewk_handle;
258 static void *cairo_handle;
259
260 /* externally accessible functions */
261 Evas_Object*
262 _elm_smart_webview_add(Evas *evas, Eina_Bool tiled)
263 {
264    Evas_Object* webview;
265    int (*ewk_init)(void) = NULL;
266    void (*ewk_dnet_open)(void) = NULL;
267    Eina_Bool (*ewk_view_single_smart_set)(Ewk_View_Smart_Class *) = NULL;
268    Eina_Bool (*ewk_view_tiled_smart_set)(Ewk_View_Smart_Class *) = NULL;
269
270    if (!_smart)
271      {
272         // init g_thread
273         g_type_init();
274         if (!g_thread_get_initialized())
275           g_thread_init(NULL);
276
277         ewk_handle = dlopen(EWEBKIT_PATH, RTLD_LAZY);
278         cairo_handle = dlopen(CAIRO_PATH, RTLD_LAZY);
279
280         // init ewk
281         if (!ewk_init)
282           ewk_init = (int (*)())dlsym(ewk_handle, "ewk_init");
283         ewk_init();
284
285         if (!ewk_dnet_open)
286           ewk_dnet_open = (void (*)())dlsym(ewk_handle, "ewk_dnet_open");
287         ewk_dnet_open();
288
289         /* create subclass */
290         static Ewk_View_Smart_Class _api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION(SMART_NAME);
291
292         if (tiled)
293           {
294              if (!ewk_view_tiled_smart_set)
295                ewk_view_tiled_smart_set = (Eina_Bool (*)(Ewk_View_Smart_Class *))dlsym(ewk_handle, "ewk_view_tiled_smart_set");
296              ewk_view_tiled_smart_set(&_api);
297              if (EINA_UNLIKELY(!_parent_sc.sc.add))
298                ewk_view_tiled_smart_set(&_parent_sc);
299
300           } else {
301                if (!ewk_view_single_smart_set)
302                  ewk_view_single_smart_set = (Eina_Bool (*)(Ewk_View_Smart_Class *))dlsym(ewk_handle, "ewk_view_single_smart_set");
303                ewk_view_single_smart_set(&_api);
304                if (EINA_UNLIKELY(!_parent_sc.sc.add))
305                  ewk_view_single_smart_set(&_parent_sc);
306           }
307
308         _api.sc.add     = _smart_add;
309         _api.sc.del     = _smart_del;
310         _api.sc.show    = _smart_show;
311         _api.sc.hide    = _smart_hide;
312         _api.sc.resize  = _smart_resize;
313         _api.sc.move  = _smart_move;
314 #ifdef DEBUG
315         _api.sc.calculate = _smart_calculate;
316 #endif
317         _api.mouse_down = _smart_mouse_down;
318         _api.mouse_up   = _smart_mouse_up  ;
319         _api.mouse_move = _smart_mouse_move;
320
321         _smart = evas_smart_class_new(&_api.sc);
322         elm_theme_overlay_add(NULL, WEBVIEW_THEME_EDJ);
323
324      }
325
326    if (!_smart)
327      {
328         ERR("could not create smart class\n");
329         return NULL;
330      }
331
332    webview = evas_object_smart_add(evas, _smart);
333    if (!webview)
334      {
335         ERR("could not create smart object for webview");
336         return NULL;
337      }
338
339    // set tiled and unused cache 
340    Smart_Data* sd = evas_object_smart_data_get(webview);
341    if (sd)
342      {
343         sd->tiled = tiled;
344         if (sd->tiled)
345           {
346              static Ewk_Tile_Unused_Cache *ewk_tile_cache;
347              if (ewk_tile_cache == NULL)
348                {
349                   if (!sd->ewk_view_tiled_unused_cache_get)
350                     sd->ewk_view_tiled_unused_cache_get = (Ewk_Tile_Unused_Cache *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_tiled_unused_cache_get");
351                   ewk_tile_cache = sd->ewk_view_tiled_unused_cache_get(webview);
352
353                   if (!sd->ewk_tile_unused_cache_max_set)
354                     sd->ewk_tile_unused_cache_max_set = (void (*)(Ewk_Tile_Unused_Cache *, size_t))dlsym(ewk_handle, "ewk_tile_unused_cache_max_set");
355                   sd->ewk_tile_unused_cache_max_set(ewk_tile_cache, MAX_TUC);
356                } else {
357                     if (!sd->ewk_view_tiled_unused_cache_set)
358                       sd->ewk_view_tiled_unused_cache_set = (void (*)(Evas_Object *, Ewk_Tile_Unused_Cache *))dlsym(ewk_handle, "ewk_view_tiled_unused_cache_set");
359                     sd->ewk_view_tiled_unused_cache_set(webview, ewk_tile_cache);
360                }
361              //size_t mem = ewk_tile_unused_cache_used_get(ewk_tile_cache);
362              //DBG("%s: Used cache: %d (%dkB)", __func__, mem, (mem/1024));
363           }
364      }
365
366    return webview;
367 }
368
369 void
370 _elm_smart_webview_events_feed_set(Evas_Object* obj, Eina_Bool feed)
371 {
372    API_ENTRY return;
373    sd->events_feed = feed;
374 }
375
376 Eina_Bool
377 _elm_smart_webview_events_feed_get(Evas_Object* obj)
378 {
379    API_ENTRY return EINA_FALSE;
380    return sd->events_feed;
381 }
382
383 void
384 _elm_smart_webview_auto_fitting_set(Evas_Object* obj, Eina_Bool enable)
385 {
386    API_ENTRY return;
387    sd->auto_fitting = enable;
388 }
389
390 Eina_Bool
391 _elm_smart_webview_auto_fitting_get(Evas_Object *obj)
392 {
393    API_ENTRY return EINA_FALSE;
394    return sd->auto_fitting;
395 }
396
397 Evas_Object *
398 _elm_smart_webview_minimap_get(Evas_Object* obj)
399 {
400    DBG("%s\n", __func__);
401    API_ENTRY return NULL;
402
403    if (sd->minimap.eo != NULL) return sd->minimap.eo;
404
405    sd->minimap.eo = edje_object_add(evas_object_evas_get(obj));
406    edje_object_file_set(sd->minimap.eo, WEBVIEW_EDJ, "minimap");
407
408    sd->minimap.content = evas_object_image_add(evas_object_evas_get(sd->minimap.eo));
409    evas_object_size_hint_align_set(sd->minimap.content, 0.5, 0.5);
410    evas_object_image_colorspace_set(sd->minimap.content, EVAS_COLORSPACE_ARGB8888);
411    evas_object_image_alpha_set(sd->minimap.content, EINA_FALSE);
412
413    Evas_Object* box = evas_object_box_add(evas_object_evas_get(sd->minimap.eo));
414    evas_object_box_append(box, sd->minimap.content);
415    evas_object_show(sd->minimap.content);
416    edje_object_part_swallow(sd->minimap.eo, "swallow.content", box);
417
418    return sd->minimap.eo;
419 }
420
421 void
422 _elm_smart_webview_uri_set(Evas_Object* obj, const char* uri)
423 {
424    API_ENTRY return;
425
426    char full_uri[MAX_URI] = "";
427    printf("<< uri [%s] >>\n", uri);
428
429    if (uri == NULL)
430      return;
431
432    // check uri string
433    int len = strlen(uri);
434    if (len)
435      {
436         if (strstr(uri, "://") == NULL) {
437              strncpy(full_uri, "http://", 7);
438              full_uri[7] = '\0';
439              len = (len >= (MAX_URI - 7)) ? (MAX_URI - 8) : len;
440              strncat(full_uri, uri, len);
441         } else {
442              len = (len >= MAX_URI) ? (MAX_URI - 1) : len;
443              strncpy(full_uri, uri, len);
444              full_uri[len] = '\0';
445         }
446
447         printf("<< full uri [%s] >>\n", full_uri);
448         if (!sd->ewk_view_uri_set)
449           sd->ewk_view_uri_set = (Eina_Bool (*)(Evas_Object *, const char *))dlsym(ewk_handle, "ewk_view_uri_set");
450         sd->ewk_view_uri_set(obj, full_uri);
451      }
452 }
453
454 void
455 _elm_smart_webview_widget_set(Evas_Object *obj, Evas_Object *wid)
456 {
457    API_ENTRY return;
458    sd->widget = wid;
459 }
460
461 /* local subsystem functions */
462 static void
463 _smart_show(Evas_Object* obj)
464 {
465    DBG("%s\n", __func__);
466    INTERNAL_ENTRY;
467
468    _elm_smart_touch_start(sd->touch_obj);
469    _parent_sc.sc.show(obj);
470 }
471
472 static void
473 _smart_hide(Evas_Object* obj)
474 {
475    DBG("%s\n", __func__);
476    INTERNAL_ENTRY;
477
478    _elm_smart_touch_stop(sd->touch_obj);
479    _parent_sc.sc.hide(obj);
480 }
481
482 static void
483 _smart_resize(Evas_Object* obj, Evas_Coord w, Evas_Coord h)
484 {
485    DBG("%s\n", __func__);
486    INTERNAL_ENTRY;
487
488    _parent_sc.sc.resize(obj, w, h);
489 }
490
491 static void
492 _smart_move(Evas_Object* obj, Evas_Coord x, Evas_Coord y)
493 {
494    DBG("%s\n", __func__);
495    INTERNAL_ENTRY;
496
497    _parent_sc.sc.move(obj, x, y);
498 }
499
500 //TODO: Is it required? I just add to test
501 static void
502 _smart_calculate(Evas_Object* obj)
503 {
504    DBG("%s\n", __func__);
505    _parent_sc.sc.calculate(obj);
506    DBG("%s end\n", __func__);
507 }
508
509 static Eina_Bool
510 _smart_mouse_down(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Down* ev)
511 {
512    DBG("%s is called\n", __func__);
513    Smart_Data *sd = (Smart_Data *)esd;
514    sd->mouse_down_copy = *ev;
515    return _parent_sc.mouse_down(esd, ev);
516 }
517
518 static Eina_Bool
519 _smart_mouse_up(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Up* ev)
520 {
521    DBG("%s is called\n", __func__);
522    Smart_Data *sd = (Smart_Data *)esd;
523    sd->mouse_up_copy = *ev;
524    if (sd->event_blocked == EINA_TRUE) return EINA_TRUE;
525    if (sd->event_only == EINA_TRUE) goto forward_event;
526
527    if (sd->animator != NULL)
528      {
529         ecore_animator_del(sd->animator);
530         sd->animator = NULL;
531      }
532    sd->hold_counter = 0;
533
534    //check if user hold touch
535    if (ev && (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
536      {
537         return EINA_TRUE;
538      }
539
540    //TODO:check if use click input or textarea
541 forward_event:
542    //return _parent_sc.mouse_up(esd, ev);
543    _smart_cb_mouse_up(NULL, esd->self, (void*)&ev->output);
544    return EINA_TRUE;
545 }
546
547 static Eina_Bool
548 _smart_mouse_move(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Move* ev)
549 {
550    //DBG("%s is called\n", __func__);
551    Smart_Data *sd = (Smart_Data *)esd;
552    if (sd->event_blocked == EINA_TRUE) return EINA_TRUE;
553    if (sd->event_only == EINA_TRUE) goto forward_event;
554
555    return EINA_TRUE;
556 forward_event:
557    return _parent_sc.mouse_move(esd, ev);
558 }
559
560 #ifdef NEED_TO_REMOVE
561 // TODO: temporary mouse callback until the webkit engine can receive mouse events
562 static void
563 _view_on_mouse_down(void* data, Evas* e, Evas_Object* o, void* event_info)
564 {
565    Evas_Event_Mouse_Down* ev = (Evas_Event_Mouse_Down*)event_info;
566    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
567    EINA_SAFETY_ON_NULL_RETURN(sd->api);
568    EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_down);
569    sd->api->mouse_down(sd, ev);
570 }
571
572 static void
573 _view_on_mouse_up(void* data, Evas* e, Evas_Object* o, void* event_info)
574 {
575    Evas_Event_Mouse_Up* ev = (Evas_Event_Mouse_Up*)event_info;
576    Ewk_View_Smart_Data* sd = (Ewk_View_Smart_Data*)data;
577    EINA_SAFETY_ON_NULL_RETURN(sd->api);
578    EINA_SAFETY_ON_NULL_RETURN(sd->api->mouse_up);
579    sd->api->mouse_up(sd, ev);
580 }
581 #endif
582
583 static void
584 _smart_load_started(void* data, Evas_Object* webview, void* error)
585 {
586    DBG("%s is called\n", __func__);
587    Smart_Data *sd = (Smart_Data *)data;
588    if (!sd) return;
589
590    // set default layout and zoom level
591    sd->is_mobile_page = EINA_FALSE;
592    sd->layout.w = sd->layout.default_w;
593    sd->zoom.init_zoom_rate = 1.0f;
594    sd->zoom.min_zoom_rate = MIN_ZOOM_RATIO;
595    sd->zoom.max_zoom_rate = MAX_ZOOM_RATIO;
596    sd->zoom.scalable = EINA_TRUE;
597 }
598
599 static void
600 _smart_load_finished(void* data, Evas_Object* webview, void* arg)
601 {
602    DBG("%s is called\n", __func__);
603    Smart_Data* sd = (Smart_Data *)data;
604    if (!sd) return;
605
606    // if error, call loadNotFoundPage
607    Ewk_Frame_Load_Error *error = (Ewk_Frame_Load_Error *) arg;
608    int errorCode = (error)? error->code: 0;
609    if ( errorCode != 0 && errorCode != -999 )
610      { // 0 ok, -999 request cancelled
611         DBG( "page not found:, [code: %d] [domain: %s] [description: %s] [failing_url: %s] \n",
612               error->code, error->domain, error->description, error->failing_url);
613         //ecore_job_add(loadNotFoundPage, (void *)this);
614         return;
615      }
616
617    if (sd->auto_fitting == EINA_TRUE)
618      {
619         if (!sd->ewk_view_zoom_set)
620           sd->ewk_view_zoom_set = (Eina_Bool (*)(Evas_Object *, float, Evas_Coord, Evas_Coord))dlsym(ewk_handle, "ewk_view_zoom_set");
621         sd->ewk_view_zoom_set(webview, sd->zoom.min_zoom_rate, 0, 0);
622      }
623
624    // update thumbnail and minimap
625    if (sd->thumbnail != NULL)
626      {
627         if (!sd->cairo_surface_destroy)
628           sd->cairo_surface_destroy = (void (*)(cairo_surface_t *))dlsym(cairo_handle, "cairo_surface_destroy");
629         sd->cairo_surface_destroy(sd->thumbnail);
630      }
631    sd->thumbnail = _image_clone_get(sd, &(sd->minimap.cw), &(sd->minimap.ch));
632
633    if (sd->minimap.eo == NULL) return;
634    _minimap_update(sd->minimap.content, sd, sd->thumbnail,
635          sd->minimap.cw, sd->minimap.ch);
636
637    if (sd->tiled)
638      _directional_pre_render(sd->base.self, 0, 0);
639 }
640
641 static void
642 _smart_load_error(void* data, Evas_Object* webview, void* arg)
643 {
644    DBG("%s is called\n", __func__);
645    Smart_Data* sd = (Smart_Data *)data;
646    if (!sd) return;
647
648    // if error, call loadNotFoundPage
649    Ewk_Frame_Load_Error *error = (Ewk_Frame_Load_Error *) arg;
650    int errorCode = (error)? error->code: 0;
651    if ( errorCode != 0 && errorCode != -999 )
652      { // 0 ok, -999 request cancelled
653         char szStrBuffer[1024];
654         snprintf(szStrBuffer, 1024, "page not found:, [code: %d] [domain: %s] [description: %s] [failing_url: %s] \n",
655               error->code, error->domain, error->description, error->failing_url);
656         DBG(szStrBuffer);
657
658         //ecore_job_add(loadNotFoundPage, (void *)this);
659         if (!sd->ewk_view_stop)
660           sd->ewk_view_stop = (Eina_Bool (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_stop");
661         sd->ewk_view_stop(webview);
662
663         if (!sd->ewk_view_frame_main_get)
664           sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
665
666         if (!sd->ewk_frame_contents_set)
667           sd->ewk_frame_contents_set = (Eina_Bool (*)(Evas_Object *, const char *, size_t, const char *, const char *, const char *))dlsym(ewk_handle, "ewk_frame_contents_set");
668         sd->ewk_frame_contents_set(sd->ewk_view_frame_main_get(webview), szStrBuffer, 0, NULL, NULL, NULL);
669         return;
670      }
671 }
672
673 static void
674 _smart_viewport_changed(void* data, Evas_Object* webview, void* arg)
675 {
676    DBG("%s is called\n", __func__);
677    Smart_Data* sd = (Smart_Data *)data;
678    if (!sd) return;
679
680    // check for mobile page
681    int layout_w, layout_h;
682    float init_zoom_rate, max_zoom_rate, min_zoom_rate;
683    Eina_Bool scalable;
684
685    if (!sd->ewk_view_viewport_get)
686      sd->ewk_view_viewport_get = (void (*)(Evas_Object *, int *, int *, float *, float *, float *, Eina_Bool *))dlsym(ewk_handle, "ewk_view_viewport_get");
687    sd->ewk_view_viewport_get(webview, &layout_w, &layout_h,
688          &init_zoom_rate, &max_zoom_rate, &min_zoom_rate, &scalable);
689
690    int object_w, object_h;
691    evas_object_geometry_get(webview, NULL, NULL, &object_w, &object_h);
692    object_w = (object_w % 10) ? (object_w / 10 * 10 + 10) : object_w;
693
694    // if layout width is bigger than object width, we regard current page to not the mobile page
695    if (layout_w > object_w)
696      {
697         sd->layout.w = layout_w;
698         return;
699      }
700
701    // set data for mobile page
702    sd->is_mobile_page = EINA_TRUE;
703    sd->layout.w = (layout_w <= 0) ? MOBILE_DEFAULT_WIDTH : layout_w;
704    sd->zoom.init_zoom_rate = (float)object_w / sd->layout.w;
705    sd->zoom.min_zoom_rate = (min_zoom_rate <= 0) ? MIN_ZOOM_RATIO : min_zoom_rate;
706    sd->zoom.max_zoom_rate = (max_zoom_rate <= 0) ? MAX_ZOOM_RATIO : max_zoom_rate;
707    sd->layout.h = (layout_h <= 0) ? (object_h / sd->zoom.init_zoom_rate) : layout_h;
708    sd->zoom.scalable = scalable;
709 }
710
711 static void
712 _smart_contents_size_changed(void* data, Evas_Object* frame, void* arg)
713 {
714    Smart_Data* sd = (Smart_Data *)data;
715    if (!sd) return;
716
717    if (!(sd->ewk_frame_view_get))
718      sd->ewk_frame_view_get = (Evas_Object * (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_frame_view_get");
719
720    Evas_Object* webview = sd->ewk_frame_view_get(frame);
721
722    Evas_Coord* size = (Evas_Coord*)arg;
723    if (!size || size[0] == 0)
724      return;
725
726    // update min zoom rate
727    int w;
728    evas_object_geometry_get(webview, NULL, NULL, &w, NULL);
729    sd->zoom.min_zoom_rate = (float)w / (float)size[0];
730    if (sd->zoom.min_zoom_rate < MIN_ZOOM_RATIO)
731      sd->zoom.min_zoom_rate = MIN_ZOOM_RATIO;
732
733    if (!sd->ewk_view_zoom_range_set)
734      sd->ewk_view_zoom_range_set = (void (*)(Evas_Object *, float, float))dlsym(ewk_handle, "ewk_view_zoom_range_set");
735    sd->ewk_view_zoom_range_set(webview, sd->zoom.min_zoom_rate, sd->zoom.max_zoom_rate);
736 }
737
738 static void
739 _smart_load_nonemptylayout_finished(void* data, Evas_Object* frame, void* arg)
740 {
741    DBG("%s is called\n", __func__);
742    Smart_Data* sd = (Smart_Data *)data;
743    if (!sd) return;
744
745    if (!sd->ewk_frame_view_get)
746      sd->ewk_frame_view_get = (Evas_Object * (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_frame_view_get");
747    Evas_Object* webview = sd->ewk_frame_view_get(frame);
748
749    if (!sd->ewk_frame_contents_size_get)
750      sd->ewk_frame_contents_size_get = (Eina_Bool (*)(const Evas_Object *, Evas_Coord *, Evas_Coord *))dlsym(ewk_handle, "ewk_frame_contents_size_get");
751    int content_w, content_h;
752    sd->ewk_frame_contents_size_get(frame, &content_w, &content_h);
753
754    if (!sd->ewk_view_user_scalable_set)
755      sd->ewk_view_user_scalable_set = (void (*)(Evas_Object *, Eina_Bool))dlsym(ewk_handle, "ewk_view_user_scalable_set");
756
757    sd->ewk_view_user_scalable_set(webview, EINA_TRUE);
758
759    if (!sd->ewk_view_zoom_range_set)
760      sd->ewk_view_zoom_range_set = (void (*)(Evas_Object *, float, float))dlsym(ewk_handle, "ewk_view_zoom_range_set");
761    if (!sd->ewk_view_fixed_layout_size_set)
762      sd->ewk_view_fixed_layout_size_set = (void (*)(Evas_Object *, Evas_Coord, Evas_Coord))dlsym(ewk_handle, "ewk_view_fixed_layout_size_set");
763
764    // set zoom and layout
765    if (sd->is_mobile_page)
766      {
767         if (!sd->ewk_view_zoom_set)
768           sd->ewk_view_zoom_set = (Eina_Bool (*)(Evas_Object *, float, Evas_Coord, Evas_Coord))dlsym(ewk_handle, "ewk_view_zoom_set");
769         sd->ewk_view_zoom_set(webview, sd->zoom.init_zoom_rate, 0, 0);
770         sd->ewk_view_zoom_range_set(webview, sd->zoom.min_zoom_rate, sd->zoom.max_zoom_rate);
771
772         sd->ewk_view_fixed_layout_size_set(webview, sd->layout.w, sd->layout.h);
773
774      } else {
775           evas_object_geometry_get(webview, NULL, NULL, NULL, &sd->layout.h);
776           if (!sd->ewk_view_zoom_set)
777             sd->ewk_view_zoom_set = (Eina_Bool (*)(Evas_Object *, float, Evas_Coord, Evas_Coord))dlsym(ewk_handle, "ewk_view_zoom_set");
778           sd->ewk_view_zoom_set(webview, sd->zoom.init_zoom_rate, 0, 0);
779           sd->ewk_view_zoom_range_set(webview, sd->zoom.min_zoom_rate, sd->zoom.max_zoom_rate);
780           sd->ewk_view_fixed_layout_size_set(webview, sd->layout.w, sd->layout.h);
781      }
782
783    sd->ewk_view_user_scalable_set(webview, sd->zoom.scalable);
784 }
785
786 static void
787 _smart_cb_view_created(void* data, Evas_Object* webview, void* arg)
788 {
789    printf("%s is called\n", __func__);
790    Smart_Data* sd = (Smart_Data *)data;
791    if (!sd) return;
792    *((Evas_Object**)arg) = webview;
793 }
794
795 static void
796 _smart_add(Evas_Object* obj)
797 {
798    DBG("%s\n", __func__);
799    Smart_Data* sd;
800
801    sd = calloc(1, sizeof(Smart_Data));
802    if (!sd) return;
803    evas_object_smart_data_set(obj, sd);
804    _parent_sc.sc.add(obj);
805
806    sd->thumbnail = NULL;
807    sd->minimap.eo = NULL;
808    sd->dropdown.options = NULL;
809    sd->dropdown.option_cnt = 0;
810    sd->animator = NULL;
811    sd->event_only = EINA_FALSE;
812    sd->text_selection_on = EINA_FALSE;
813    sd->events_feed = EINA_FALSE;
814    sd->event_blocked = EINA_TRUE;
815    sd->touch_obj = _elm_smart_touch_add(evas_object_evas_get(obj));
816    sd->layout.default_w = DEFAULT_LAYOUT_WIDTH;
817
818    sd->ewk_view_theme_set = (void (*)(Evas_Object *, const char *))dlsym(ewk_handle, "ewk_view_theme_set");
819    sd->ewk_view_theme_set(obj, WEBKIT_EDJ);
820
821    sd->ewk_view_zoom_text_only_set = (Eina_Bool (*)(Evas_Object *, Eina_Bool))dlsym(ewk_handle, "ewk_view_zoom_text_only_set");
822    sd->ewk_view_zoom_text_only_set(obj, EINA_FALSE);
823    sd->ewk_view_zoom_cairo_scaling_set = (Eina_Bool (*)(Evas_Object *, Eina_Bool))dlsym(ewk_handle, "ewk_view_zoom_cairo_scaling_set");
824    sd->ewk_view_zoom_cairo_scaling_set(obj, EINA_TRUE);
825
826 #ifdef NEED_TO_REMOVE
827    // TODO: temporary add the mouse callbacks until the webkit engine can receive mouse events
828    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN, _view_on_mouse_down, sd);
829    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP, _view_on_mouse_up, sd);
830 #endif
831
832    evas_object_smart_callback_add(obj, "load,started", _smart_load_started, sd);
833    evas_object_smart_callback_add(obj, "load,finished", _smart_load_finished, sd);
834    evas_object_smart_callback_add(obj, "load,error", _smart_load_error, sd);
835    evas_object_smart_callback_add(obj, "viewport,changed", _smart_viewport_changed, sd);
836
837    evas_object_smart_callback_add(obj, "webview,created", _smart_cb_view_created, sd); // I need to consider more
838
839    if (!(sd->ewk_view_frame_main_get))
840      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
841    evas_object_smart_callback_add(sd->ewk_view_frame_main_get(obj), "contents,size,changed",
842          _smart_contents_size_changed, sd);
843    evas_object_smart_callback_add(sd->ewk_view_frame_main_get(obj), "load,nonemptylayout,finished",
844          _smart_load_nonemptylayout_finished, sd);
845
846    evas_object_smart_callback_add(obj, "one,press", _smart_cb_mouse_down, sd);
847    evas_object_smart_callback_add(obj, "one,release", _smart_cb_mouse_up, sd);
848    evas_object_smart_callback_add(obj, "one,single,tap", _smart_cb_mouse_tap, sd);
849    evas_object_smart_callback_add(obj, "one,long,press", _smart_cb_select_closest_word, sd);
850    evas_object_smart_callback_add(obj, "one,double,tap", _smart_cb_smart_zoom, sd);
851    evas_object_smart_callback_add(obj, "one,move,start", _smart_cb_pan_start, sd);
852    evas_object_smart_callback_add(obj, "one,move", _smart_cb_pan_by, sd);
853    evas_object_smart_callback_add(obj, "one,move,end", _smart_cb_pan_stop, sd);
854    evas_object_smart_callback_add(obj, "two,move,start", _smart_cb_pinch_zoom_start, sd);
855    evas_object_smart_callback_add(obj, "two,move", _smart_cb_pinch_zoom_move, sd);
856    evas_object_smart_callback_add(obj, "two,move,end", _smart_cb_pinch_zoom_stop, sd);
857
858    evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
859    evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
860
861    _elm_smart_touch_child_set(sd->touch_obj, obj);
862    _text_selection_init(obj);
863 }
864
865 static void
866 _smart_del(Evas_Object* obj)
867 {
868    DBG("%s\n", __func__);
869    INTERNAL_ENTRY;
870
871    if (sd->minimap.eo != NULL)
872      {
873         evas_object_del(sd->minimap.eo);
874         sd->minimap.eo = NULL;
875      }
876    _parent_sc.sc.del(obj);
877 }
878
879 static void
880 _directional_pre_render(Evas_Object* obj, int dx, int dy)
881 {
882    INTERNAL_ENTRY;
883
884    if (!sd->ewk_view_frame_main_get)
885      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
886    if (!sd->ewk_frame_visible_content_geometry_get)
887      sd->ewk_frame_visible_content_geometry_get = (Eina_Bool (*)(const Evas_Object *, Eina_Bool, int *, int *, int *, int *))dlsym(ewk_handle, "ewk_frame_visible_content_geometry_get");
888    int x, y, w, h;
889    sd->ewk_frame_visible_content_geometry_get(sd->ewk_view_frame_main_get(obj), false, &x, &y, &w, &h);
890    DBG("visible content: (%d, %d, %d, %d)", x, y, w, h);
891
892    typedef enum { up, down, left, right, up_left, up_right, down_left, down_right, undefined } Directions;
893    Directions direction = undefined;
894
895    if (dx == 0 && dy <  0) direction = down;
896    if (dx >  0 && dy <  0) direction = down_left;
897    if (dx >  0 && dy == 0) direction = left;
898    if (dx >  0 && dy >  0) direction = up_left;
899    if (dx == 0 && dy >  0) direction = up;
900    if (dx <  0 && dy >  0) direction = up_right;
901    if (dx <  0 && dy == 0) direction = right;
902    if (dx <  0 && dy <  0) direction = down_right;
903
904    const float DIRECTION_PLAIN_CX = 1.5;
905    const float DIRECTION_CROSS_CX = 0.7;
906    const float DIRECTION_UNDEFINED_CX_LEVEL_1 = 0.3;
907    const float DIRECTION_UNDEFINED_CX_LEVEL_2 = 0.6;
908    const float DIRECTION_UNDEFINED_CX_LEVEL_3 = 0.8;
909    int p_x = x, p_y = y, p_w = w, p_h = h;
910
911    switch (direction) {
912       case up:
913          DBG("Direction: up");
914          p_y = y - h * DIRECTION_PLAIN_CX;
915          p_h = h * DIRECTION_PLAIN_CX;
916          break;
917       case up_right:
918          DBG("Direction: up_right");
919          p_w = w + w * DIRECTION_CROSS_CX;
920          p_y = y - h * DIRECTION_CROSS_CX;
921          p_h = h + h * DIRECTION_CROSS_CX;
922          break;
923       case right:
924          DBG("Direction: right");
925          p_x = x + w;
926          p_w = w * DIRECTION_PLAIN_CX;
927          break;
928       case down_right:
929          DBG("Direction: down_right");
930          p_w = w + w * DIRECTION_CROSS_CX;
931          p_h = h + h * DIRECTION_CROSS_CX;
932          break;
933       case down:
934          DBG("Direction: down");
935          p_y = y + h;
936          p_h = h * DIRECTION_PLAIN_CX;
937          break;
938       case down_left:
939          DBG("Direction: down_left");
940          p_x = x - w * DIRECTION_CROSS_CX;
941          p_w = w + w * DIRECTION_CROSS_CX;
942          p_h = h + h * DIRECTION_CROSS_CX;
943          break;
944       case left:
945          DBG("Direction: left");
946          p_x = x - w * DIRECTION_PLAIN_CX;
947          p_w = w * DIRECTION_PLAIN_CX;
948          break;
949       case up_left:
950          DBG("Direction: left_up");
951          p_x = x - w * DIRECTION_CROSS_CX;
952          p_w = w + w * DIRECTION_CROSS_CX;
953          p_y = y - h * DIRECTION_CROSS_CX;
954          p_h = h + h * DIRECTION_CROSS_CX;
955          break;
956       case undefined:
957          DBG("Direction: undefined");
958          break;
959       default:
960          DBG("Shouldn't happen!!");
961    }
962
963    if (!sd->ewk_view_zoom_get)
964      sd->ewk_view_zoom_get = (float (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_zoom_get");
965    float zoom = sd->ewk_view_zoom_get(obj);
966
967    // cancel the previously scheduled pre-rendering
968    // This makes sense especilaly for zooming operation - when user
969    // finishes zooming, and pre-render for the previous zoom was
970    // not finished, it doesn't make sense to continue pre-rendering for the previous zoom
971    if (!sd->ewk_view_pre_render_cancel)
972      sd->ewk_view_pre_render_cancel = (void (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_pre_render_cancel");
973    sd->ewk_view_pre_render_cancel(obj);
974
975    if (!sd->ewk_view_pre_render_region)
976      sd->ewk_view_pre_render_region = (Eina_Bool (*)(Evas_Object *, Evas_Coord, Evas_Coord, Evas_Coord, Evas_Coord, float))dlsym(ewk_handle, "ewk_view_pre_render_region");
977
978    if (direction != undefined)
979      {
980         /* Queue tiles in the direction of the last panning */
981         DBG("pre rendering - directional - content: (%d, %d, %d, %d), zoom %.3f",p_x, p_y, p_w, p_h, zoom);
982
983         sd->ewk_view_pre_render_region(obj, p_x, p_y, p_w, p_h, zoom);
984         //dbg_draw_scaled_area(obj, 0, p_x, p_y, p_w, p_h);
985      }
986    else
987      {
988         DBG("pre rendering - directional - skipped");
989         //dbg_draw_scaled_area(obj, 0, 0, 0, 0, 0);
990      }
991
992    /* Queue tiles in a small rectangle around the viewport */
993    p_x = x - w * DIRECTION_UNDEFINED_CX_LEVEL_1;
994    p_y = y - h * DIRECTION_UNDEFINED_CX_LEVEL_1;
995    p_w = w + 2.0 * w * DIRECTION_UNDEFINED_CX_LEVEL_1;
996    p_h = h + 2.0 * h * DIRECTION_UNDEFINED_CX_LEVEL_1;
997    DBG("pre rendering - small - content: (%d, %d, %d, %d), zoom %.3f", p_x, p_y, p_w, p_h, zoom);
998    sd->ewk_view_pre_render_region(obj, p_x, p_y, p_w, p_h, zoom);
999    //dbg_draw_scaled_area(obj, 1, p_x, p_y, p_w, p_h);
1000
1001    /* Queue tiles in a medium rectangle around the viewport */
1002    p_x = x - w * DIRECTION_UNDEFINED_CX_LEVEL_2;
1003    p_y = y - h * DIRECTION_UNDEFINED_CX_LEVEL_2;
1004    p_w = w + 2.0 * w * DIRECTION_UNDEFINED_CX_LEVEL_2;
1005    p_h = h + 2.0 * h * DIRECTION_UNDEFINED_CX_LEVEL_2;
1006    DBG("pre rendering - medium - content: (%d, %d, %d, %d), zoom %.3f", p_x, p_y, p_w, p_h, zoom);
1007    sd->ewk_view_pre_render_region(obj, p_x, p_y, p_w, p_h, zoom);
1008    //dbg_draw_scaled_area(obj, 2, p_x, p_y, p_w, p_h);
1009
1010    /* Queue tiles in a large rectangle around the viewport */
1011    p_x = x - w * DIRECTION_UNDEFINED_CX_LEVEL_3;
1012    p_y = y - h * DIRECTION_UNDEFINED_CX_LEVEL_3;
1013    p_w = w + 2.0 * w * DIRECTION_UNDEFINED_CX_LEVEL_3;
1014    p_h = h + 2.0 * h * DIRECTION_UNDEFINED_CX_LEVEL_3;
1015    DBG("pre rendering - large - content: (%d, %d, %d, %d), zoom %.3f", p_x, p_y, p_w, p_h, zoom);
1016    sd->ewk_view_pre_render_region(obj, p_x, p_y, p_w, p_h, zoom);
1017    //dbg_draw_scaled_area(obj, 3, p_x, p_y, p_w, p_h);
1018
1019    /* Log some statistics */
1020    /*
1021       int v_w, v_h;
1022       evas_object_geometry_get(obj, NULL, NULL, &v_w, &v_h);
1023       Ewk_Tile_Unused_Cache *tuc = ewk_view_tiled_unused_cache_get(obj);
1024       size_t used = ewk_tile_unused_cache_used_get(tuc);
1025       size_t max = ewk_tile_unused_cache_max_get(tuc);
1026    // Will this work for non cairo scaling?
1027    int est = (zoomRatio*p_w * zoomRatio*p_h - v_w * v_h) * 4; // 4 bytes per pixel
1028    DBG("pre rendering - Cache max = %.1fMB  Cache used = %.1fMB  Estimated size of pre-render area: %.1fMB\n", 
1029    max/1024.0/1024.0, used/1024.0/1024.0, est/1024.0/1024.0);
1030    if (est > max)
1031    DBG("WARNING!! estimated size of pre-render are is larger than the cache size. This will result in inefficient use of cache!");
1032    */
1033 }
1034
1035 static void
1036 _smart_cb_mouse_down(void* data, Evas_Object* webview, void* ev)
1037 {
1038    DBG("%s\n", __func__);
1039    Smart_Data* sd = (Smart_Data *)data;
1040    if (!sd) return;
1041    //Evas_Point* point = (Evas_Point*)ev;
1042
1043    if (sd->text_selection_on == EINA_TRUE) return;
1044
1045    evas_object_focus_set(webview, EINA_TRUE);
1046    if (!sd->ewk_view_frame_main_get)
1047      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1048    if (!sd->ewk_frame_feed_focus_in)
1049      sd->ewk_frame_feed_focus_in = (Eina_Bool (*)(Evas_Object *))dlsym(ewk_handle, "ewk_frame_feed_focus_in");
1050    sd->ewk_frame_feed_focus_in(sd->ewk_view_frame_main_get(webview));
1051    _parent_sc.mouse_down((Ewk_View_Smart_Data*)sd, &sd->mouse_down_copy);
1052 }
1053
1054 static void
1055 _smart_cb_mouse_up(void* data, Evas_Object* webview, void* ev)
1056 {
1057    DBG("%s\n", __func__);
1058    Smart_Data* sd = (Smart_Data *)data;
1059    if (!sd) return;
1060
1061    Evas_Point* point = (Evas_Point*)ev;
1062    DBG(" argument : (%d, %d)\n", point->x, point->y);
1063
1064    if (sd->events_feed == EINA_TRUE)
1065      _parent_sc.mouse_up((Ewk_View_Smart_Data*)sd, &sd->mouse_up_copy);
1066 }
1067
1068 static void
1069 _smart_cb_mouse_tap(void* data, Evas_Object* webview, void* ev)
1070 {
1071    DBG("%s\n", __func__);
1072    Smart_Data* sd = (Smart_Data *)data;
1073    if (!sd) return;
1074
1075    Evas_Point* point = (Evas_Point*)ev;
1076    DBG(" argument : (%d, %d)\n", point->x, point->y);
1077
1078    // check for video link
1079    int ewk_x, ewk_y;
1080    _coords_evas_to_ewk(webview, point->x, point->y, &ewk_x, &ewk_y);
1081    Eina_Bool have_link = EINA_FALSE;
1082    Eina_Bool have_image = EINA_FALSE;
1083    char *link_url = NULL, *link_text = NULL, *image_url = NULL;
1084    if (!sd->ewk_page_check_point)
1085      sd->ewk_page_check_point = (Eina_Bool (*)(Evas_Object *, int, int, Evas_Event_Mouse_Down *, Eina_Bool *, Eina_Bool *, char **, char **, char **))dlsym(ewk_handle, "ewk_page_check_point");
1086    sd->ewk_page_check_point(webview, ewk_x, ewk_y, &sd->mouse_down_copy,
1087          &have_link, &have_image, &link_url, &link_text, &image_url);
1088    if (link_url) free(link_url);
1089    if (link_text) free(link_text);
1090    if (image_url) free(image_url);
1091
1092    //TODO: below code is not based on open source (need to check and refactor)
1093    int x = 0, y = 0;
1094    _unzoom_position(webview, point->x, point->y, &x, &y);
1095
1096    // check for input field
1097    if (!sd->ewk_page_check_point_for_keyboard)
1098      sd->ewk_page_check_point_for_keyboard = (char * (*)(Evas_Object *, int, int, Eina_Bool *))dlsym(ewk_handle, "ewk_page_check_point_for_keyboard");
1099    if (!sd->ewk_page_dropdown_get_options)
1100      sd->ewk_page_dropdown_get_options = (char ** (*)(Evas_Object *, int, int, int *, int *))dlsym(ewk_handle, "ewk_page_dropdown_get_options");
1101
1102    Eina_Bool have_input_field;
1103    sd->ewk_page_check_point_for_keyboard(webview, x, y, &have_input_field);
1104    if (have_input_field == EINA_TRUE)
1105      {
1106         _zoom_to_rect(sd, point->x, point->y);
1107
1108         // check whether it is radio
1109      }
1110    else if (NULL != (sd->dropdown.options = sd->ewk_page_dropdown_get_options(webview, x, y,
1111                &sd->dropdown.option_cnt, &sd->dropdown.option_idx)))
1112      {
1113         Evas* evas;
1114         evas = evas_object_evas_get(webview);
1115
1116         // show discpicker
1117         Evas_Object* discpicker = elm_discpicker_add(webview);
1118         if (discpicker)
1119           {
1120              // set items
1121              int i;
1122              Elm_Discpicker_Item* item;
1123              for (i = 0; i < sd->dropdown.option_cnt; i++)
1124                {
1125                   item = elm_discpicker_item_append(discpicker, sd->dropdown.options[i], NULL, NULL);
1126                   if (i == sd->dropdown.option_idx)
1127                     {
1128                        elm_discpicker_item_selected_set(item);
1129                     }
1130                }
1131
1132              // selected callback
1133              void discpicker_selected_cb(void* data, Evas_Object* obj, void* event_info)
1134                {
1135                   Smart_Data* sd = (Smart_Data *)data;
1136                   if (!sd) return;
1137                   Evas_Object* webview = sd->base.self;
1138
1139                   int x = 0, y = 0;
1140                   Evas_Point* point = &sd->mouse_up_copy.output;
1141                   _unzoom_position(webview, point->x, point->y, &x, &y);
1142
1143                   Elm_Discpicker_Item* item = event_info;
1144                   const char *selected_label = elm_discpicker_item_label_get(item);
1145                   int selected_index;
1146                   for (selected_index = 0; selected_index < sd->dropdown.option_cnt; selected_index++)
1147                     {
1148                        if (!strcmp(selected_label, sd->dropdown.options[selected_index]))
1149                          {
1150                             break;
1151                          }
1152                     }
1153                   printf("<< selected [%d | %s] >>\n", selected_index, selected_label);
1154                   if (!sd->ewk_page_dropdown_set_current_index)
1155                     sd->ewk_page_dropdown_set_current_index = (Eina_Bool (*)(Evas_Object *, int, int, int))dlsym(ewk_handle, "ewk_page_dropdown_set_current_index");
1156                   sd->ewk_page_dropdown_set_current_index(webview, x, y, selected_index);
1157                   //evas_object_del(obj);
1158                }
1159
1160              // show discpicker
1161              evas_object_smart_callback_add(discpicker, "selected", discpicker_selected_cb, sd);
1162              elm_discpicker_row_height_set(discpicker, 80);
1163              evas_object_resize(discpicker, 480, 400);
1164              evas_object_move(discpicker, 0, 400);
1165              evas_object_show(discpicker);
1166           }
1167      }
1168
1169    if (sd->text_selection_on == EINA_TRUE)
1170      {
1171         _smart_cb_unselect_closest_word(sd, webview, NULL);
1172         return;
1173      }
1174
1175    _parent_sc.mouse_up((Ewk_View_Smart_Data*)sd, &sd->mouse_up_copy);
1176 }
1177
1178 static void
1179 _smart_cb_pan_start(void* data, Evas_Object* webview, void* ev)
1180 {
1181    DBG("%s\n", __func__);
1182    Smart_Data* sd = (Smart_Data *)data;
1183    if (!sd) return;
1184    Evas_Point* point = (Evas_Point*)ev;
1185
1186    sd->pan_s = *point;
1187    sd->on_panning = EINA_TRUE;
1188
1189    if (sd->tiled)
1190      {
1191         if (!sd->ewk_view_pre_render_cancel)
1192           sd->ewk_view_pre_render_cancel = (void (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_pre_render_cancel");
1193         sd->ewk_view_pre_render_cancel(webview);
1194      }
1195
1196    if (!sd->ewk_view_suspend_request)
1197      sd->ewk_view_suspend_request = (Eina_Bool (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_suspend_request");
1198    sd->ewk_view_suspend_request(webview); // suspend network loading
1199
1200    if (sd->text_selection_on == EINA_TRUE)
1201      {
1202         if (_text_selection_handle_pressed(sd, point->x, point->y))
1203           _elm_smart_touch_is_one_drag_mode_enable(sd->touch_obj, EINA_FALSE);
1204      }
1205
1206    sd->locked_dx = 0;
1207    sd->locked_dy = 0;
1208 }
1209
1210 static void
1211 _smart_cb_pan_by(void* data, Evas_Object* webview, void* ev)
1212 {
1213    //DBG("%s\n", __func__);
1214    Smart_Data* sd = (Smart_Data *)data;
1215    if (!sd) return;
1216    Evas_Point* point = (Evas_Point*)ev;
1217
1218    if (sd->on_panning == EINA_FALSE) return;
1219
1220    if (sd->text_selection_on == EINA_TRUE)
1221      {
1222         if (sd->text_selection.front_handle_moving == EINA_TRUE
1223               || sd->text_selection.back_handle_moving == EINA_TRUE)
1224           {
1225              _text_selection_update_position(sd, point->x, point->y);
1226              return;
1227           }
1228      }
1229
1230    if (sd->events_feed == EINA_TRUE)
1231      {
1232         Evas* evas = evas_object_evas_get(webview);
1233         Evas_Modifier *modifiers = (Evas_Modifier *)evas_key_modifier_get(evas);
1234         Evas_Lock *locks = (Evas_Lock *)evas_key_lock_get(evas);
1235
1236         Evas_Event_Mouse_Move event_move;
1237         event_move.buttons = 1;
1238         event_move.cur.output.x = point->x;
1239         event_move.cur.output.y = point->y;
1240         event_move.cur.canvas.x = point->x;
1241         event_move.cur.canvas.y = point->y;
1242         event_move.data = NULL;
1243         event_move.modifiers = modifiers;
1244         event_move.locks = locks;
1245         event_move.timestamp = ecore_loop_time_get();
1246         event_move.event_flags = EVAS_EVENT_FLAG_NONE;
1247         event_move.dev = NULL;
1248
1249         _parent_sc.mouse_move((Ewk_View_Smart_Data*)sd, &event_move);
1250         return;
1251      }
1252
1253    if (!sd->ewk_frame_scroll_pos_get)
1254      sd->ewk_frame_scroll_pos_get = (Eina_Bool (*)(const Evas_Object *, int *, int *))dlsym(ewk_handle, "ewk_frame_scroll_pos_get");
1255
1256    int dx = sd->pan_s.x - point->x;
1257    int dy = sd->pan_s.y - point->y;
1258
1259    if (!sd->ewk_view_frame_main_get)
1260      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1261
1262    int old_x, old_y;
1263    sd->ewk_frame_scroll_pos_get(sd->ewk_view_frame_main_get(webview), &old_x, &old_y);
1264
1265    if (!sd->ewk_frame_contents_size_get)
1266      sd->ewk_frame_contents_size_get = (Eina_Bool (*)(const Evas_Object *, Evas_Coord *, Evas_Coord *))dlsym(ewk_handle, "ewk_frame_contents_size_get");
1267
1268    int content_w, content_h;
1269    sd->ewk_frame_contents_size_get(sd->ewk_view_frame_main_get(webview), &content_w, &content_h);
1270    if (!sd->ewk_view_zoom_get)
1271      sd->ewk_view_zoom_get = (float (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_zoom_get");
1272    float zoom = sd->ewk_view_zoom_get(webview);
1273    content_w *= zoom;
1274    content_h *= zoom;
1275    DBG("<< ========content [%d, %d] new pos [%d, %d] >>\n", content_w, content_h, old_x + dx, old_y + dy);
1276
1277    if ((old_x + dx) >= 0 && (old_x + dx) <= content_w && !elm_widget_drag_lock_x_get(sd->widget))
1278      elm_widget_drag_lock_x_set(sd->widget, EINA_TRUE);
1279    if ((old_y + dy) >= 0 && (old_y + dy) <= content_h && !elm_widget_drag_lock_y_get(sd->widget))
1280      elm_widget_drag_lock_y_set(sd->widget, EINA_TRUE);
1281
1282    Eina_Bool locked = EINA_FALSE;
1283    if (!elm_widget_drag_lock_x_get(sd->widget))
1284      {
1285         if ((sd->locked_dx > 0 && (sd->locked_dx + dx) <= 0)
1286               || (sd->locked_dx < 0 && (sd->locked_dx + dx) >= 0))
1287           {
1288              elm_widget_drag_lock_x_set(sd->widget, EINA_TRUE);
1289              DBG("===============<< widget x lock >>\n");
1290              dx += sd->locked_dx;
1291
1292           }
1293         else
1294           {
1295              sd->locked_dx += dx;
1296              locked = EINA_TRUE;
1297           }
1298      }
1299
1300    if (!elm_widget_drag_lock_y_get(sd->widget))
1301      {
1302         if ((sd->locked_dy > 0 && (sd->locked_dy + dy) <= 0)
1303               || (sd->locked_dy < 0 && (sd->locked_dy + dy) >= 0))
1304           {
1305              elm_widget_drag_lock_y_set(sd->widget, EINA_TRUE);
1306              DBG("===============<< widget y lock >>\n");
1307              dy += sd->locked_dy;
1308
1309           }
1310         else
1311           {
1312              sd->locked_dy += dy;
1313              locked = EINA_TRUE;
1314           }
1315      }
1316
1317    if (locked) return;
1318
1319    if (!sd->ewk_view_frame_main_get)
1320      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1321    if (!sd->ewk_frame_scroll_add)
1322      sd->ewk_frame_scroll_add = (Eina_Bool (*)(Evas_Object *, int, int))dlsym(ewk_handle, "ewk_frame_scroll_add");
1323    sd->ewk_frame_scroll_add(sd->ewk_view_frame_main_get(webview), dx, dy);
1324
1325    _minimap_update(sd->minimap.content, sd, sd->thumbnail,
1326          sd->minimap.cw, sd->minimap.ch);
1327    sd->pan_s = *point;
1328
1329    int new_x, new_y;
1330    sd->ewk_frame_scroll_pos_get(sd->ewk_view_frame_main_get(webview), &new_x, &new_y);
1331
1332    if (sd->text_selection_on == EINA_TRUE)
1333      _text_selection_move_by(sd, old_x - new_x, old_y - new_y);
1334
1335    if (dx && elm_widget_drag_lock_x_get(sd->widget) && (old_x == new_x))
1336      {
1337         sd->locked_dx = dx - (old_x - new_x);
1338         elm_widget_drag_lock_x_set(sd->widget, EINA_FALSE);
1339         DBG("===============<< widget x unlock >>\n");
1340      }
1341
1342    if (dy && elm_widget_drag_lock_y_get(sd->widget) && (old_y == new_y))
1343      {
1344         sd->locked_dy = dy - (old_y - new_y);
1345         elm_widget_drag_lock_y_set(sd->widget, EINA_FALSE);
1346         DBG("===============<< widget y unlock >>\n");
1347      }
1348 }
1349
1350 static void
1351 _smart_cb_pan_stop(void* data, Evas_Object* webview, void* ev)
1352 {
1353    DBG("%s\n", __func__);
1354    Smart_Data* sd = (Smart_Data *)data;
1355    if (!sd) return;
1356    Evas_Point* point = (Evas_Point*)ev;
1357    sd->on_panning = EINA_FALSE;
1358
1359    if (sd->text_selection_on == EINA_TRUE)
1360      {
1361         if (sd->text_selection.front_handle_moving == EINA_TRUE
1362               || sd->text_selection.back_handle_moving == EINA_TRUE)
1363           _elm_smart_touch_is_one_drag_mode_enable(sd->touch_obj, EINA_TRUE);
1364         sd->text_selection.front_handle_moving = EINA_FALSE;
1365         sd->text_selection.back_handle_moving = EINA_FALSE;
1366      }
1367
1368    if (sd->tiled)
1369      {
1370         if (!sd->ewk_view_tiled_unused_cache_get)
1371           sd->ewk_view_tiled_unused_cache_get = (Ewk_Tile_Unused_Cache *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_tiled_unused_cache_get");
1372         if (!sd->ewk_tile_unused_cache_used_get)
1373           sd->ewk_tile_unused_cache_used_get = (size_t (*)(const Ewk_Tile_Unused_Cache *))dlsym(ewk_handle, "ewk_tile_unused_cache_used_get");
1374         if (!sd->ewk_tile_unused_cache_max_get)
1375           sd->ewk_tile_unused_cache_max_get = (size_t (*)(const Ewk_Tile_Unused_Cache *))dlsym(ewk_handle, "ewk_tile_unused_cache_max_get");
1376         Ewk_Tile_Unused_Cache *tuc = sd->ewk_view_tiled_unused_cache_get(webview);
1377         size_t used = sd->ewk_tile_unused_cache_used_get(tuc);
1378         size_t max = sd->ewk_tile_unused_cache_max_get(tuc);
1379         DBG("[%s] max = %d  used = %d \n", __func__, max, used);
1380         if (used > max)
1381           {
1382              if (!sd->ewk_tile_unused_cache_auto_flush)
1383                sd->ewk_tile_unused_cache_auto_flush = (void (*)(Ewk_Tile_Unused_Cache *))dlsym(ewk_handle, "ewk_tile_unused_cache_auto_flush");
1384              sd->ewk_tile_unused_cache_auto_flush(tuc);
1385           }
1386         _directional_pre_render(webview,
1387               (sd->mouse_down_copy.canvas.x - point->x), (sd->mouse_down_copy.canvas.y - point->y));
1388      }
1389
1390    if (!sd->ewk_view_resume_request)
1391      sd->ewk_view_resume_request = (Eina_Bool (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_resume_request");
1392    sd->ewk_view_resume_request(webview); // resume network loading
1393
1394    if (elm_widget_drag_lock_x_get(sd->widget))
1395      {
1396         DBG("==============<< widget x unlock >>\n");
1397         elm_widget_drag_lock_x_set(sd->widget, EINA_FALSE);
1398      }
1399
1400    if (elm_widget_drag_lock_y_get(sd->widget))
1401      {
1402         DBG("==============<< widget y unlock >>\n");
1403         elm_widget_drag_lock_y_set(sd->widget, EINA_FALSE);
1404      }
1405 }
1406
1407 static void
1408 _smart_cb_select_closest_word(void* data, Evas_Object* webview, void* ev)
1409 {
1410    DBG("%s\n", __func__);
1411    Smart_Data* sd = (Smart_Data *)data;
1412    if (!sd) return;
1413    Evas_Point* point = (Evas_Point*)ev;
1414
1415    int x, y;
1416    _coords_evas_to_ewk(webview, point->x, point->y, &x, &y);
1417
1418    if (!sd->ewk_view_frame_main_get)
1419      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1420    if (!sd->ewk_frame_select_closest_word)
1421      sd->ewk_frame_select_closest_word = (Eina_Bool (*)(Evas_Object *, int, int, int *, int *, int *, int *, int *, int *))dlsym(ewk_handle, "ewk_frame_select_closest_word");
1422    int tx, ty, th, bx, by, bh;
1423    Eina_Bool ret = sd->ewk_frame_select_closest_word(sd->ewk_view_frame_main_get(webview), x, y,
1424          &tx, &ty, &th, &bx, &by, &bh);
1425    if (ret)
1426      {
1427         _coords_ewk_to_evas(webview, tx, ty, &tx, &ty);
1428         _coords_ewk_to_evas(webview, bx, by, &bx, &by);
1429         _text_selection_show();
1430         _text_selection_set_front_info(sd, tx, ty, th);
1431         _text_selection_set_back_info(sd, bx, by, bh);
1432         sd->text_selection_on = EINA_TRUE;
1433      }
1434 }
1435
1436 static void
1437 _smart_cb_unselect_closest_word(void* data, Evas_Object* webview, void* ev)
1438 {
1439    DBG("%s\n", __func__);
1440    Smart_Data* sd = (Smart_Data *)data;
1441    if (!sd) return;
1442
1443    if (sd->text_selection_on == EINA_TRUE)
1444      {
1445         _text_selection_hide(sd);
1446         if (!sd->ewk_view_select_none)
1447           sd->ewk_view_select_none = (Eina_Bool (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_select_none");
1448         sd->ewk_view_select_none(webview);
1449         sd->text_selection_on = EINA_FALSE;
1450      }
1451 }
1452
1453 // zoom
1454 static const int ZOOM_STEP_TRESHOLD = 20;
1455 static const float ZOOM_STEP_RATIO_STEP = 0.1f;
1456
1457 #define ZOOM_FRAMERATE 60
1458 #define N_COSINE 18
1459 static const float cosine[N_COSINE] =
1460 { 1.0f, 0.99f, 0.96f, 0.93f, 0.88f, 0.82f, 0.75f, 0.67f, 0.59f, 0.5f,
1461    0.41f, 0.33f, 0.25f, 0.18f, 0.12f, 0.07f, 0.01f, 0.0f };
1462 static int smart_zoom_index = N_COSINE - 1;
1463
1464 #define INPUT_LOCATION_X 20
1465 #define INPUT_LOCATION_Y 50
1466 #define INPUT_ZOOM_RATIO 2.5
1467
1468 static void
1469 _suspend_all(Smart_Data *sd)
1470 {
1471    Evas_Object *webview = sd->base.self;
1472
1473    if (!sd->ewk_view_disable_render)
1474      sd->ewk_view_disable_render = (Eina_Bool (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_disable_render");
1475    sd->ewk_view_disable_render(webview);
1476
1477    if (!sd->ewk_view_setting_enable_plugins_get)
1478      sd->ewk_view_setting_enable_plugins_get = (Eina_Bool (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_setting_enable_plugins_get");
1479    if (sd->ewk_view_setting_enable_plugins_get(webview))
1480      {
1481         if (!sd->ewk_view_pause_and_or_hide_plugins)
1482           sd->ewk_view_pause_and_or_hide_plugins = (void (*)(Evas_Object *, Eina_Bool, Eina_Bool))dlsym(ewk_handle, "ewk_view_pause_and_or_hide_plugins");
1483         sd->ewk_view_pause_and_or_hide_plugins(webview, EINA_FALSE, EINA_TRUE);
1484      }
1485    if (sd->tiled)
1486      {
1487         if (!sd->ewk_view_pre_render_cancel)
1488           sd->ewk_view_pre_render_cancel = (void (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_pre_render_cancel");
1489         sd->ewk_view_pre_render_cancel(webview);
1490      }
1491
1492    if (!sd->ewk_view_suspend_request)
1493      sd->ewk_view_suspend_request = (Eina_Bool (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_suspend_request");
1494    sd->ewk_view_suspend_request(webview); // suspend network loading
1495
1496 }
1497
1498 static void
1499 _resume_all(Smart_Data *sd)
1500 {
1501    Evas_Object *webview = sd->base.self;
1502
1503    if (sd->tiled)
1504      {
1505         if (!sd->ewk_view_enable_render)
1506           sd->ewk_view_enable_render = (Eina_Bool (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_enable_render");
1507         sd->ewk_view_enable_render(webview);
1508      }
1509    if (!sd->ewk_view_pause_and_or_hide_plugins)
1510      sd->ewk_view_pause_and_or_hide_plugins = (void (*)(Evas_Object *, Eina_Bool, Eina_Bool))dlsym(ewk_handle, "ewk_view_pause_and_or_hide_plugins");
1511    sd->ewk_view_pause_and_or_hide_plugins(webview, EINA_FALSE, EINA_TRUE);
1512
1513    if (!sd->ewk_view_resume_request)
1514      sd->ewk_view_resume_request = (Eina_Bool (*)(Evas_Object *))dlsym(ewk_handle, "ewk_view_resume_request");
1515    sd->ewk_view_resume_request(webview);
1516 }
1517
1518 static void
1519 _zoom_start(Smart_Data* sd, int centerX, int centerY, int distance)
1520 {
1521    DBG("%s\n", __func__);
1522    sd->zoom.basis.x = centerX;
1523    sd->zoom.basis.y = centerY;
1524    sd->zoom.finger_distance = distance;
1525    sd->zoom.zooming_level = 0;
1526    sd->on_zooming = EINA_TRUE;
1527    if (!sd->ewk_view_zoom_get)
1528      sd->ewk_view_zoom_get = (float (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_zoom_get");
1529    sd->zoom.zoom_rate_at_start = sd->ewk_view_zoom_get(sd->base.self);
1530
1531    _suspend_all(sd);
1532
1533    if (sd->text_selection_on == EINA_TRUE)
1534      _text_selection_hide(sd);
1535 }
1536
1537 static void
1538 _zoom_move(Smart_Data* sd, int centerX, int centerY, int distance)
1539 {
1540    if (sd->on_zooming == EINA_FALSE) return;
1541    //DBG("%s\n", __func__);
1542
1543    int zoom_distance = distance - sd->zoom.finger_distance;
1544    int new_level = zoom_distance / ZOOM_STEP_TRESHOLD;
1545
1546    if (new_level != sd->zoom.zooming_level)
1547      {
1548         sd->zoom.zooming_level = new_level;
1549         float zoom_ratio = sd->zoom.zoom_rate_at_start + new_level * ZOOM_STEP_RATIO_STEP;
1550
1551         if (zoom_ratio  < sd->zoom.min_zoom_rate)
1552           zoom_ratio = sd->zoom.min_zoom_rate;
1553         if (zoom_ratio > MAX_ZOOM_RATIO)
1554           zoom_ratio = MAX_ZOOM_RATIO;
1555         sd->zoom.zooming_rate = zoom_ratio;
1556
1557         //printf("new zoom : %f, (%d, %d)\n", zoom_ratio, centerX, centerY);
1558         if (!sd->ewk_view_zoom_weak_set)
1559           sd->ewk_view_zoom_weak_set = (Eina_Bool (*)(Evas_Object *, float, Evas_Coord, Evas_Coord))dlsym(ewk_handle, "ewk_view_zoom_weak_set");
1560         sd->ewk_view_zoom_weak_set(sd->base.self, zoom_ratio, sd->zoom.basis.x, sd->zoom.basis.y);
1561      }
1562 }
1563
1564 static void
1565 _zoom_stop(Smart_Data* sd)
1566 {
1567    sd->on_zooming = EINA_FALSE;
1568    DBG("%s ( %d )\n", __func__, sd->zoom.zooming_level);
1569    if (sd->zoom.zooming_level == 0) return;
1570
1571    if (!sd->ewk_view_zoom_set)
1572      sd->ewk_view_zoom_set = (Eina_Bool (*)(Evas_Object *, float, Evas_Coord, Evas_Coord))dlsym(ewk_handle, "ewk_view_zoom_set");
1573    sd->ewk_view_zoom_set(sd->base.self, sd->zoom.zooming_rate, sd->zoom.basis.x, sd->zoom.basis.y);
1574
1575    if (sd->tiled)
1576      {
1577         if (!sd->ewk_view_tiled_unused_cache_get)
1578           sd->ewk_view_tiled_unused_cache_get = (Ewk_Tile_Unused_Cache *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_tiled_unused_cache_get");
1579         Ewk_Tile_Unused_Cache* ewk_tile_cache = sd->ewk_view_tiled_unused_cache_get(sd->base.self);
1580         if (!sd->ewk_tile_unused_cache_auto_flush)
1581           sd->ewk_tile_unused_cache_auto_flush = (void (*)(Ewk_Tile_Unused_Cache *))dlsym(ewk_handle, "ewk_tile_unused_cache_auto_flush");
1582         sd->ewk_tile_unused_cache_auto_flush(ewk_tile_cache);
1583         _directional_pre_render(sd->base.self, 0, 0);
1584      }
1585
1586    _resume_all(sd);
1587
1588    if (sd->text_selection_on == EINA_TRUE)
1589      {
1590         if (!sd->ewk_view_frame_main_get)
1591           sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1592         if (!sd->ewk_frame_selection_handlers_get)
1593           sd->ewk_frame_selection_handlers_get = (Eina_Bool (*)(Evas_Object *, int *, int *, int *, int *, int *, int *))dlsym(ewk_handle, "ewk_frame_selection_handlers_get");
1594         int tx, ty, th, bx, by, bh;
1595         sd->ewk_frame_selection_handlers_get(sd->ewk_view_frame_main_get(sd->base.self), &tx, &ty, &th, &bx, &by, &bh);
1596         _coords_ewk_to_evas(sd->base.self, tx, ty, &tx, &ty);
1597         _coords_ewk_to_evas(sd->base.self, bx, by, &bx, &by);
1598         _text_selection_show();
1599         _text_selection_set_front_info(sd, tx, ty, th);
1600         _text_selection_set_back_info(sd, bx, by, bh);
1601      }
1602 }
1603
1604 static void
1605 _adjust_to_contents_boundary(Evas_Object* obj, int* to_x, int* to_y,
1606       int from_x, int from_y, float new_zoom_rate)
1607 {
1608    INTERNAL_ENTRY;
1609    // get view's geometry
1610    int view_x, view_y, view_w, view_h;
1611    evas_object_geometry_get(obj, &view_x, &view_y, &view_w, &view_h);
1612
1613    // get contentsSize
1614    if (!sd->ewk_view_frame_main_get)
1615      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1616    if (!sd->ewk_frame_contents_size_get)
1617      sd->ewk_frame_contents_size_get = (Eina_Bool (*)(const Evas_Object *, Evas_Coord *, Evas_Coord *))dlsym(ewk_handle, "ewk_frame_contents_size_get");
1618
1619    int contents_w, contents_h;
1620    sd->ewk_frame_contents_size_get(sd->ewk_view_frame_main_get(obj), &contents_w, &contents_h);
1621    if (!sd->ewk_view_zoom_get)
1622      sd->ewk_view_zoom_get = (float (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_zoom_get");
1623    float current_zoom_rate = sd->ewk_view_zoom_get(obj);
1624    if (!sd->ewk_view_zoom_cairo_scaling_get)
1625      sd->ewk_view_zoom_cairo_scaling_get = (Eina_Bool (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_zoom_cairo_scaling_get");
1626    if (sd->ewk_view_zoom_cairo_scaling_get(obj))
1627      {
1628         contents_w *= current_zoom_rate;
1629         contents_h *= current_zoom_rate;
1630      }
1631
1632    // check boundary - should not exceed the left, right, top and bottom of contents after zoom
1633    float zoom_step = new_zoom_rate / current_zoom_rate;
1634    int ewk_from_x, ewk_from_y;
1635    _coords_evas_to_ewk(obj, from_x, from_y, &ewk_from_x, &ewk_from_y);
1636    int contents_left = ewk_from_x * zoom_step; // left contents size of from
1637    int contents_right = contents_w * zoom_step - contents_left; // right contents size of from
1638    int screen_left = (*to_x) - view_x;
1639    int screen_right = view_w - screen_left;
1640    if (contents_left < screen_left)
1641      (*to_x) -= (screen_left - contents_left);
1642    else if (contents_right < screen_right)
1643      (*to_x) += (screen_right - contents_right);
1644    int contents_top = ewk_from_y * zoom_step; // top contents size of from
1645    int contents_bottom = contents_h * zoom_step - contents_top; // bottom contents size of from
1646    int screen_top = (*to_y) - view_y;
1647    int screen_bottom = view_h - screen_top;
1648    if (contents_top < screen_top)
1649      (*to_y) -= (screen_top - contents_top);
1650    else if (contents_bottom < screen_bottom)
1651      (*to_y) += (screen_bottom - contents_bottom);
1652 }
1653
1654 static int
1655 _smart_zoom_animator(void* data)
1656 {
1657    Smart_Data* sd = (Smart_Data*)data;
1658
1659    if (!sd->ewk_view_frame_main_get)
1660      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1661
1662    // stop
1663    if (smart_zoom_index < 0)
1664      {
1665         if (!sd->ewk_view_zoom_set)
1666           sd->ewk_view_zoom_set = (Eina_Bool (*)(Evas_Object *, float, Evas_Coord, Evas_Coord))dlsym(ewk_handle, "ewk_view_zoom_set");
1667         sd->ewk_view_zoom_set(sd->base.self, sd->zoom.zoom_rate_to_set,
1668               sd->zoom.basis.x, sd->zoom.basis.y);
1669         if (sd->smart_zoom_animator)
1670           {
1671              ecore_animator_del(sd->smart_zoom_animator);
1672              sd->smart_zoom_animator = NULL;
1673           }
1674
1675         _elm_smart_touch_start(sd->touch_obj);
1676
1677         _resume_all(sd);
1678
1679         if (sd->text_selection_on == EINA_TRUE)
1680           {
1681              if (!sd->ewk_frame_selection_handlers_get)
1682                sd->ewk_frame_selection_handlers_get = (Eina_Bool (*)(Evas_Object *, int *, int *, int *, int *, int *, int *))dlsym(ewk_handle, "ewk_frame_selection_handlers_get");
1683              int tx, ty, th, bx, by, bh;
1684              sd->ewk_frame_selection_handlers_get(sd->ewk_view_frame_main_get(sd->base.self),
1685                    &tx, &ty, &th, &bx, &by, &bh);
1686              _coords_ewk_to_evas(sd->base.self, tx, ty, &tx, &ty);
1687              _coords_ewk_to_evas(sd->base.self, bx, by, &bx, &by);
1688              _text_selection_show();
1689              _text_selection_set_front_info(sd, tx, ty, th);
1690              _text_selection_set_back_info(sd, bx, by, bh);
1691           }
1692
1693         return ECORE_CALLBACK_CANCEL;
1694      }
1695
1696    if (sd->zoom.zoom_rate_at_start != sd->zoom.zoom_rate_to_set)
1697      {
1698         // weak zoom
1699         float zoom_rate = sd->zoom.zoom_rate_at_start
1700            + ((sd->zoom.zoom_rate_to_set - sd->zoom.zoom_rate_at_start) * cosine[smart_zoom_index]);
1701         if (!sd->ewk_view_zoom_weak_set)
1702           sd->ewk_view_zoom_weak_set = (Eina_Bool (*)(Evas_Object *, float, Evas_Coord, Evas_Coord))dlsym(ewk_handle, "ewk_view_zoom_weak_set");
1703         sd->ewk_view_zoom_weak_set(sd->base.self, zoom_rate, sd->zoom.basis.x, sd->zoom.basis.y);
1704      } else {
1705           if (!sd->ewk_frame_scroll_pos_get)
1706             sd->ewk_frame_scroll_pos_get = (Eina_Bool (*)(const Evas_Object *, int *, int *))dlsym(ewk_handle, "ewk_frame_scroll_pos_get");
1707           // save old scroll positions
1708           int current_scroll_x, current_scroll_y;
1709           sd->ewk_frame_scroll_pos_get(sd->ewk_view_frame_main_get(sd->base.self), &current_scroll_x, &current_scroll_y);
1710
1711           // get to set position
1712           int to_set_x = sd->zoom.scroll_at_start.x
1713              + (sd->zoom.scroll_to_set.x - sd->zoom.scroll_at_start.x) * cosine[smart_zoom_index];
1714           int to_set_y = sd->zoom.scroll_at_start.y
1715              + (sd->zoom.scroll_to_set.y - sd->zoom.scroll_at_start.y) * cosine[smart_zoom_index];
1716
1717           if (!sd->ewk_frame_scroll_add)
1718             sd->ewk_frame_scroll_add = (Eina_Bool (*)(Evas_Object *, int, int))dlsym(ewk_handle, "ewk_frame_scroll_add");
1719           // scroll
1720           sd->ewk_frame_scroll_add(sd->ewk_view_frame_main_get(sd->base.self),
1721                 to_set_x - current_scroll_x, to_set_y - current_scroll_y);
1722      }
1723    smart_zoom_index--;
1724
1725    return ECORE_CALLBACK_RENEW;
1726 }
1727
1728 static void
1729 _smart_cb_pinch_zoom_start(void* data, Evas_Object* webview, void* event_info)
1730 {
1731    //DBG("%s\n", __func__);
1732    Smart_Data *sd = (Smart_Data *)data;
1733    if (!sd) return;
1734
1735    Evas_Point* arr = (Evas_Point*) event_info;
1736    int centerX = (arr[0].x + arr[1].x) / 2;
1737    int centerY = (arr[0].y + arr[1].y) / 2;
1738    int dx = arr[0].x - arr[1].x;
1739    int dy = arr[0].y - arr[1].y;
1740    int distance = sqrt((double)(dx * dx + dy * dy));
1741    _zoom_start(sd, centerX, centerY, distance);
1742 }
1743
1744 static void
1745 _smart_cb_pinch_zoom_move(void* data, Evas_Object* webview, void* event_info)
1746 {
1747    //DBG("%s\n", __func__);
1748    Smart_Data *sd = (Smart_Data *)data;
1749    if (!sd) return;
1750
1751    Evas_Point* arr = (Evas_Point*) event_info;
1752    int centerX = (arr[0].x + arr[1].x) / 2;
1753    int centerY = (arr[0].y + arr[1].y) / 2;
1754    int dx = arr[0].x - arr[1].x;
1755    int dy = arr[0].y - arr[1].y;
1756    int distance = sqrt((double)(dx * dx + dy * dy));
1757    _zoom_move(sd, centerX, centerY, distance);
1758 }
1759
1760 static void
1761 _smart_cb_pinch_zoom_stop(void* data, Evas_Object* webview, void* event_info)
1762 {
1763    //DBG("%s\n", __func__);
1764    Smart_Data *sd = (Smart_Data *)data;
1765    if (!sd) return;
1766
1767    _zoom_stop(sd);
1768    _minimap_update(sd->minimap.content, sd, sd->thumbnail, sd->minimap.cw, sd->minimap.ch);
1769
1770    if (sd->tiled)
1771      {
1772         if (!sd->ewk_view_tiled_unused_cache_get)
1773           sd->ewk_view_tiled_unused_cache_get = (Ewk_Tile_Unused_Cache *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_tiled_unused_cache_get");
1774         Ewk_Tile_Unused_Cache *tuc = sd->ewk_view_tiled_unused_cache_get(webview);
1775         if (!sd->ewk_tile_unused_cache_used_get)
1776           sd->ewk_tile_unused_cache_used_get = (size_t (*)(const Ewk_Tile_Unused_Cache *))dlsym(ewk_handle, "ewk_tile_unused_cache_used_get");
1777         size_t used = sd->ewk_tile_unused_cache_used_get(tuc);
1778         if (!sd->ewk_tile_unused_cache_max_get)
1779           sd->ewk_tile_unused_cache_max_get = (size_t (*)(const Ewk_Tile_Unused_Cache *))dlsym(ewk_handle, "ewk_tile_unused_cache_max_get");
1780         size_t max = sd->ewk_tile_unused_cache_max_get(tuc);
1781         DBG("[%s] max = %d  used = %d \n", __func__, max, used);
1782         if (used > max)
1783           {
1784              if (!sd->ewk_tile_unused_cache_auto_flush)
1785                sd->ewk_tile_unused_cache_auto_flush = (void (*)(Ewk_Tile_Unused_Cache *))dlsym(ewk_handle, "ewk_tile_unused_cache_auto_flush");
1786              sd->ewk_tile_unused_cache_auto_flush(tuc);
1787           }
1788      }
1789 }
1790
1791 static void
1792 _smart_cb_vertical_zoom_start(void* data, Evas_Object* webview, void* event_info)
1793 {
1794    DBG("%s\n", __func__);
1795    Smart_Data *sd = (Smart_Data *)data;
1796    if (!sd) return;
1797
1798    Evas_Point* arr = (Evas_Point*) event_info;
1799    int centerX = (arr[0].x + arr[1].x) / 2;
1800    int centerY = (arr[0].y + arr[1].y) / 2;
1801    //int dx = arr[0].x - arr[1].x;
1802    //int dy = arr[0].y - arr[1].y;
1803    //int distance = sqrt((double)(dx * dx + dy * dy));
1804    _zoom_start(sd, centerX, centerY, centerY);
1805 }
1806
1807 static void
1808 _smart_cb_vertical_zoom_move(void* data, Evas_Object* webview, void* event_info)
1809 {
1810    DBG("%s\n", __func__);
1811    Smart_Data *sd = (Smart_Data *)data;
1812    if (!sd) return;
1813
1814    Evas_Point* arr = (Evas_Point*) event_info;
1815    int centerX = (arr[0].x + arr[1].x) / 2;
1816    int centerY = (arr[0].y + arr[1].y) / 2;
1817    //int dx = arr[0].x - arr[1].x;
1818    //int dy = arr[0].y - arr[1].y;
1819    //int distance = centerY - sd->zoom.cy;
1820    _zoom_move(sd, centerX, centerY, centerY);
1821 }
1822
1823 static void
1824 _smart_cb_vertical_zoom_stop(void* data, Evas_Object* webview, void* event_info)
1825 {
1826    DBG("%s\n", __func__);
1827    Smart_Data *sd = (Smart_Data *)data;
1828    if (!sd) return;
1829
1830    _zoom_stop(sd);
1831    _minimap_update(sd->minimap.content, sd, sd->thumbnail, sd->minimap.cw, sd->minimap.ch);
1832 }
1833
1834 static void
1835 _smart_cb_smart_zoom(void* data, Evas_Object* webview, void* event_info)
1836 {
1837    DBG("%s\n", __func__);
1838    Smart_Data *sd = (Smart_Data *)data;
1839    if (!sd) return;
1840    Evas_Point* point = (Evas_Point*)event_info;
1841
1842    if (!sd->ewk_view_frame_main_get)
1843      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1844
1845    // feed double tap
1846    if (sd->events_feed == EINA_TRUE)
1847      {
1848         Evas_Event_Mouse_Down mouse_double_down = sd->mouse_down_copy;
1849         mouse_double_down.flags |= EVAS_BUTTON_DOUBLE_CLICK;
1850         if (!sd->ewk_frame_feed_mouse_down)
1851           sd->ewk_frame_feed_mouse_down = (Eina_Bool (*)(Evas_Object *, const Evas_Event_Mouse_Down *))dlsym(ewk_handle, "ewk_frame_feed_mouse_down");
1852         if (!sd->ewk_frame_feed_mouse_up)
1853           sd->ewk_frame_feed_mouse_up = (Eina_Bool (*)(Evas_Object *, const Evas_Event_Mouse_Up *))dlsym(ewk_handle, "ewk_frame_feed_mouse_up");
1854         sd->ewk_frame_feed_mouse_down(sd->ewk_view_frame_main_get(sd->base.self), &mouse_double_down);
1855         sd->ewk_frame_feed_mouse_up(sd->ewk_view_frame_main_get(sd->base.self), &sd->mouse_up_copy);
1856         return;
1857      }
1858
1859    _elm_smart_touch_stop(sd->touch_obj);
1860
1861    // get rect
1862    int ewk_x = 0, ewk_y = 0;
1863    Eina_Rectangle rect;
1864    _coords_evas_to_ewk(webview, point->x, point->y, &ewk_x, &ewk_y);
1865    if (!sd->ewk_view_get_smart_zoom_rect)
1866      sd->ewk_view_get_smart_zoom_rect = (Eina_Bool (*)(Evas_Object *, int, int, const Evas_Event_Mouse_Up *, Eina_Rectangle *))dlsym(ewk_handle, "ewk_view_get_smart_zoom_rect");
1867    sd->ewk_view_get_smart_zoom_rect(webview, ewk_x, ewk_y, &sd->mouse_up_copy, &rect);
1868
1869    // calculate zoom_rate and center of rect
1870    int view_x, view_y, view_w, view_h;
1871    evas_object_geometry_get(webview, &view_x, &view_y, &view_w, &view_h);
1872    if (!sd->ewk_view_zoom_get)
1873      sd->ewk_view_zoom_get = (float (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_zoom_get");
1874    float current_zoom_rate = sd->ewk_view_zoom_get(webview);
1875    float zoom_rate;
1876    int rect_center_x, rect_center_y;
1877    if (rect.w)
1878      {
1879         zoom_rate = current_zoom_rate * (float)view_w / (float)rect.w;
1880         _coords_ewk_to_evas(webview, rect.x + (rect.w >> 1), rect.y + (rect.h >> 1), &rect_center_x, &rect_center_y);
1881         if ((rect.h / current_zoom_rate) * zoom_rate > view_h)
1882           {
1883              rect_center_y = point->y;
1884           }
1885         // check zoom rate
1886         if (zoom_rate < (float)MIN_ZOOM_RATIO)
1887           zoom_rate = (float)MIN_ZOOM_RATIO;
1888         if (zoom_rate < sd->zoom.min_zoom_rate)
1889           zoom_rate = sd->zoom.min_zoom_rate;
1890         if (zoom_rate > (float)MAX_ZOOM_RATIO)
1891           zoom_rate = (float)MAX_ZOOM_RATIO;
1892         if (zoom_rate == current_zoom_rate)
1893           zoom_rate = sd->zoom.min_zoom_rate;
1894      } else {
1895           zoom_rate = sd->zoom.min_zoom_rate;
1896           rect_center_x = point->x;
1897           rect_center_y = point->y;
1898      }
1899
1900    // set zooming data
1901    float zoom_step = zoom_rate / current_zoom_rate;
1902    int center_x = view_x + (view_w >> 1);
1903    int center_y = view_y + (view_h >> 1);
1904
1905    _adjust_to_contents_boundary(webview, &center_x, &center_y, rect_center_x, rect_center_y, zoom_rate);
1906
1907    // set data for smart zoom
1908    sd->zoom.basis.x = (center_x - zoom_step * rect_center_x) / (1 - zoom_step);
1909    sd->zoom.basis.y = (center_y - zoom_step * rect_center_y) / (1 - zoom_step) - view_y;
1910    sd->zoom.zoom_rate_at_start = current_zoom_rate;
1911    sd->zoom.zoom_rate_to_set = zoom_rate;
1912    smart_zoom_index = N_COSINE - 1;
1913
1914    _suspend_all(sd);
1915
1916    // run animator
1917    ecore_animator_frametime_set(1.0 / ZOOM_FRAMERATE);
1918    sd->smart_zoom_animator = ecore_animator_add(_smart_zoom_animator, sd);
1919
1920    // hide textSelection handlers during zooming
1921    if (sd->text_selection_on == EINA_TRUE)
1922      _text_selection_hide(sd);
1923 }
1924
1925 static void
1926 _zoom_to_rect(Smart_Data *sd, int x, int y)
1927 {
1928    DBG("%s\n", __func__);
1929    Evas_Object *webview = sd->base.self;
1930
1931    if (!sd->ewk_view_frame_main_get)
1932      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
1933
1934    // performing a hit test
1935    _coords_evas_to_ewk(webview, x, y, &x, &y);
1936    if (!sd->ewk_frame_hit_test_new)
1937      sd->ewk_frame_hit_test_new = (Ewk_Hit_Test * (*)(const Evas_Object *, int, int))dlsym(ewk_handle, "ewk_frame_hit_test_new");
1938    Ewk_Hit_Test *hit_test = sd->ewk_frame_hit_test_new(sd->ewk_view_frame_main_get(webview), x, y);
1939
1940    // calculate zoom_rate and center of rect
1941    if (hit_test->bounding_box.w && hit_test->bounding_box.h)
1942      {
1943         // set zooming data
1944         float zoom_rate = INPUT_ZOOM_RATIO;
1945         if (!sd->ewk_view_zoom_get)
1946           sd->ewk_view_zoom_get = (float (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_zoom_get");
1947         float current_zoom_rate = sd->ewk_view_zoom_get(webview);
1948         float zoom_step = zoom_rate / current_zoom_rate;
1949
1950         // get position to move from
1951         int view_x, view_y, view_w, view_h;
1952         evas_object_geometry_get(webview, &view_x, &view_y, &view_w, &view_h);
1953         int from_x, from_y;
1954         _coords_ewk_to_evas(webview, hit_test->bounding_box.x, hit_test->bounding_box.y, &from_x, &from_y);
1955         from_x = from_x + ((view_w - INPUT_LOCATION_X) / 2) / zoom_step;
1956         from_y = from_y + hit_test->bounding_box.h / 2;
1957
1958         // get position to move to
1959         int to_x = view_x + INPUT_LOCATION_X + (view_w - INPUT_LOCATION_X) / 2;
1960         int to_y = view_y + INPUT_LOCATION_Y + (hit_test->bounding_box.h / 2) * zoom_step;
1961
1962         // adjust to contents
1963         _adjust_to_contents_boundary(webview, &to_x, &to_y, from_x, from_y, zoom_rate);
1964
1965         // set data for smart zoom
1966         sd->zoom.basis.x = (to_x - zoom_step * from_x) / (1 - zoom_step);
1967         sd->zoom.basis.y = (to_y - zoom_step * from_y) / (1 - zoom_step) - view_y;
1968         sd->zoom.zoom_rate_at_start = current_zoom_rate;
1969         sd->zoom.zoom_rate_to_set = zoom_rate;
1970         if (!sd->ewk_frame_scroll_pos_get)
1971           sd->ewk_frame_scroll_pos_get = (Eina_Bool (*)(const Evas_Object *, int *, int *))dlsym(ewk_handle, "ewk_frame_scroll_pos_get");
1972         sd->ewk_frame_scroll_pos_get(sd->ewk_view_frame_main_get(webview),
1973               &sd->zoom.scroll_at_start.x, &sd->zoom.scroll_at_start.y);
1974         sd->zoom.scroll_to_set.x = sd->zoom.scroll_at_start.x + (from_x - to_x);
1975         sd->zoom.scroll_to_set.y = sd->zoom.scroll_at_start.y + (from_y - to_y);
1976         smart_zoom_index = N_COSINE - 1;
1977
1978         _suspend_all(sd);
1979
1980         // run animator
1981         ecore_animator_frametime_set(1.0 / ZOOM_FRAMERATE);
1982         sd->smart_zoom_animator = ecore_animator_add(_smart_zoom_animator, sd);
1983      }
1984
1985    if (!sd->ewk_frame_hit_test_free)
1986      sd->ewk_frame_hit_test_free = (void (*)(Ewk_Hit_Test *))dlsym(ewk_handle, "ewk_frame_hit_test_free");
1987    sd->ewk_frame_hit_test_free(hit_test);
1988 }
1989
1990 // text-selection
1991 #define BAR_WIDTH            4
1992 #define BAR_HEIGHT           10
1993 #define HANDLE_WIDTH         60
1994 #define HANDLE_HEIGHT        60
1995 #define HANDLE_PRESS_RANGE   50
1996 #define HANDLE_MIDDLE_LENGTH 60
1997
1998 static Evas_Object* front_bar_icon;
1999 static Evas_Object* front_handle_icon;
2000 static Evas_Object* back_bar_icon;
2001 static Evas_Object* back_handle_icon;
2002
2003 static Eina_Bool initialized = EINA_FALSE;
2004
2005 static void
2006 _text_selection_init(Evas_Object* parent)
2007 {
2008    DBG("<< %s >>\n", __FUNCTION__);
2009
2010    if (initialized)
2011      return;
2012
2013    // front bar
2014    front_bar_icon = (Evas_Object*)elm_icon_add(parent);
2015    elm_icon_standard_set(front_bar_icon, "webview/ts_bar");
2016    elm_icon_scale_set(front_bar_icon, true, true);
2017    evas_object_pass_events_set(front_bar_icon, true);
2018
2019    // front handle
2020    front_handle_icon = (Evas_Object*)elm_icon_add(parent);
2021    elm_icon_standard_set(front_handle_icon, "webview/ts_handle_front");
2022    elm_icon_scale_set(front_handle_icon, false, false);
2023    evas_object_pass_events_set(front_handle_icon, true);
2024
2025    // back bar
2026    back_bar_icon = (Evas_Object*)elm_icon_add(parent);
2027    elm_icon_standard_set(back_bar_icon, "webview/ts_bar");
2028    elm_icon_scale_set(back_bar_icon, true, true);
2029    evas_object_pass_events_set(back_bar_icon, true);
2030
2031    // back handle
2032    back_handle_icon = (Evas_Object*)elm_icon_add(parent);
2033    elm_icon_standard_set(back_handle_icon, "webview/ts_handle_back");
2034    elm_icon_scale_set(back_handle_icon, false, false);
2035    evas_object_pass_events_set(back_handle_icon, true);
2036
2037    initialized = EINA_TRUE;
2038 }
2039
2040 static void
2041 _text_selection_show(void)
2042 {
2043    evas_object_show(front_bar_icon);
2044    evas_object_show(front_handle_icon);
2045    evas_object_show(back_bar_icon);
2046    evas_object_show(back_handle_icon);
2047 }
2048
2049 static void
2050 _text_selection_hide(Smart_Data *sd)
2051 {
2052    evas_object_hide(front_bar_icon);
2053    evas_object_hide(front_handle_icon);
2054    evas_object_hide(back_bar_icon);
2055    evas_object_hide(back_handle_icon);
2056
2057    sd->text_selection.front.x = -1;
2058    sd->text_selection.front.y = -1;
2059    sd->text_selection.front.h = -1;
2060    sd->text_selection.front_handle.x = -1;
2061    sd->text_selection.front_handle.y = -1;
2062    sd->text_selection.back.x = -1;
2063    sd->text_selection.back.y = -1;
2064    sd->text_selection.back.h = -1;
2065    sd->text_selection.back_handle.x = -1;
2066    sd->text_selection.back_handle.y = -1;
2067 }
2068
2069 static void
2070 _text_selection_set_front_info(Smart_Data *sd, int x, int y, int height)
2071 {
2072    Evas_Object *webview = sd->base.self;
2073
2074    Evas_Coord_Rectangle* front = &(sd->text_selection.front);
2075    Evas_Point* front_handle = &(sd->text_selection.front_handle);
2076
2077    front->h = height;
2078    int front_bar_height = height + HANDLE_MIDDLE_LENGTH + HANDLE_HEIGHT;
2079
2080    // set size
2081    evas_object_resize(front_bar_icon, BAR_WIDTH, front_bar_height);
2082    evas_object_resize(front_handle_icon, HANDLE_WIDTH, HANDLE_HEIGHT);
2083
2084    // set location
2085    front_handle->x = x - (HANDLE_WIDTH / 2);
2086    int win_y, win_height, win_bottom;
2087    evas_object_geometry_get(webview, NULL, &win_y, NULL, &win_height);
2088    win_bottom = win_y + win_height;
2089    if ((front_handle->y == -1 && (y + front_bar_height > win_bottom))
2090          || ((front_handle->y < front->y) && (y + front->h - front_bar_height > win_y))
2091          || ((front_handle->y > front->y) && (y + front_bar_height > win_bottom)))
2092      { // upper handle
2093         front_handle->y = y + front->h - front_bar_height + (HANDLE_HEIGHT / 2);
2094         evas_object_move(front_bar_icon, x, y + front->h - front_bar_height);
2095         evas_object_move(front_handle_icon, x - HANDLE_WIDTH, y + front->h - front_bar_height);
2096
2097      }
2098    else
2099      { // lower handle
2100         front_handle->y = y + front_bar_height - (HANDLE_HEIGHT / 2);
2101         evas_object_move(front_bar_icon, x, y);
2102         evas_object_move(front_handle_icon, x - HANDLE_WIDTH, front_handle->y - (HANDLE_HEIGHT / 2));
2103      }
2104
2105    front->x = x;
2106    front->y = y;
2107 }
2108
2109 static void
2110 _text_selection_set_back_info(Smart_Data *sd, int x, int y, int height)
2111 {
2112    Evas_Object *webview = sd->base.self;
2113
2114    Evas_Coord_Rectangle* back = &(sd->text_selection.back);
2115    Evas_Point* back_handle = &(sd->text_selection.back_handle);
2116
2117    back->h = height;
2118    int back_bar_height = height + HANDLE_MIDDLE_LENGTH + HANDLE_HEIGHT;
2119
2120    // set size
2121    evas_object_resize(back_bar_icon, BAR_WIDTH, back_bar_height);
2122    evas_object_resize(back_handle_icon, HANDLE_WIDTH, HANDLE_HEIGHT);
2123
2124    // set location
2125    back_handle->x = x + (HANDLE_WIDTH / 2);
2126    int win_y, win_height, win_bottom;
2127    evas_object_geometry_get(webview, NULL, &win_y, NULL, &win_height);
2128    win_bottom = win_y + win_height;
2129    if ((back_handle->y == -1 && (y - back->h + back_bar_height > win_bottom))
2130          || ((back_handle->y < back->y) && (y - back_bar_height > win_y))
2131          || ((back_handle->y > back->y) && (y - back->h + back_bar_height > win_bottom))) { // upper handle
2132         back_handle->y = y - back->h - HANDLE_MIDDLE_LENGTH - (HANDLE_HEIGHT / 2);
2133         evas_object_move(back_bar_icon, x - BAR_WIDTH, y - back_bar_height);
2134         evas_object_move(back_handle_icon, x, back_handle->y - (HANDLE_HEIGHT / 2));
2135
2136    } else {
2137         back_handle->y = y + HANDLE_MIDDLE_LENGTH + (HANDLE_HEIGHT / 2);
2138         evas_object_move(back_bar_icon, x - BAR_WIDTH, y - back->h);
2139         evas_object_move(back_handle_icon, x, back_handle->y - (HANDLE_HEIGHT / 2));
2140    }
2141
2142    back->x = x;
2143    back->y = y;
2144 }
2145
2146 static Eina_Bool
2147 _text_selection_handle_pressed(Smart_Data *sd, int x, int y)
2148 {
2149    Evas_Point front_handle = sd->text_selection.front_handle;
2150    Evas_Point back_handle = sd->text_selection.back_handle;
2151
2152    // check front handle
2153    if (x > (front_handle.x - HANDLE_PRESS_RANGE) && x < (front_handle.x + HANDLE_PRESS_RANGE)
2154          && y > (front_handle.y - HANDLE_PRESS_RANGE) && y < (front_handle.y + HANDLE_PRESS_RANGE))
2155      sd->text_selection.front_handle_moving = EINA_TRUE;
2156
2157    // check back handle
2158    if (x > (back_handle.x - HANDLE_PRESS_RANGE) && x < (back_handle.x + HANDLE_PRESS_RANGE)
2159          && y > (back_handle.y - HANDLE_PRESS_RANGE) && y < (back_handle.y + HANDLE_PRESS_RANGE))
2160      {
2161         if (sd->text_selection.front_handle_moving == EINA_TRUE)
2162           {
2163              if (abs(x - front_handle.x) + abs(y - front_handle.y)
2164                    > abs(x - back_handle.x) + abs(y - back_handle.y))
2165                {
2166                   sd->text_selection.front_handle_moving = EINA_FALSE;
2167                   sd->text_selection.back_handle_moving = EINA_TRUE;
2168                }
2169           }
2170         else
2171           {
2172              sd->text_selection.back_handle_moving = EINA_TRUE;
2173           }
2174      }
2175
2176    return (sd->text_selection.front_handle_moving || sd->text_selection.back_handle_moving);
2177 }
2178
2179 static void
2180 _text_selection_update_position(Smart_Data *sd, int x, int y)
2181 {
2182    Evas_Object *webview = sd->base.self;
2183
2184    Evas_Coord_Rectangle* front = &(sd->text_selection.front);
2185    Evas_Coord_Rectangle* back = &(sd->text_selection.back);
2186
2187    if (!sd->ewk_view_frame_main_get)
2188      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
2189
2190    // set selected region with front handle
2191    if (sd->text_selection.front_handle_moving == EINA_TRUE)
2192      {
2193         x = x + (HANDLE_WIDTH >> 1);
2194         if (sd->text_selection.front_handle.y < sd->text_selection.front.y)
2195           y = y + (HANDLE_HEIGHT >> 1) + HANDLE_MIDDLE_LENGTH;
2196         else
2197           y = y - front->h - HANDLE_MIDDLE_LENGTH - (HANDLE_HEIGHT >> 1);
2198
2199         if (y > back->y)
2200           y = back->y - back->h / 2;
2201
2202         if (!sd->ewk_frame_selection_left_set)
2203           sd->ewk_frame_selection_left_set = (Eina_Bool (*)(Evas_Object *, int, int, int *, int *, int *))dlsym(ewk_handle, "ewk_frame_selection_left_set");
2204         int ewkX, ewkY;
2205         _coords_evas_to_ewk(webview, x, y, &ewkX, &ewkY);
2206         if (sd->ewk_frame_selection_left_set(sd->ewk_view_frame_main_get(webview), ewkX, ewkY,
2207                  &front->x, &front->y, &front->h)) {
2208              _coords_ewk_to_evas(webview, front->x, front->y, &front->x, &front->y);
2209              _text_selection_set_front_info(sd, front->x, front->y, front->h);
2210         }
2211
2212         // set selected region with back handle
2213      }
2214    else if (sd->text_selection.back_handle_moving)
2215      {
2216         x = x - (HANDLE_WIDTH >> 1);
2217         if (sd->text_selection.back_handle.y < sd->text_selection.back.y)
2218           y = y + (HANDLE_HEIGHT >> 1) + HANDLE_MIDDLE_LENGTH;
2219         else
2220           y = y - back->h - HANDLE_MIDDLE_LENGTH - (HANDLE_HEIGHT >> 1);
2221
2222         if (y < front->y)
2223           y = front->y + front->h / 2;
2224
2225         if (!sd->ewk_frame_selection_right_set)
2226           sd->ewk_frame_selection_right_set = (Eina_Bool (*)(Evas_Object *, int, int, int *, int *, int *))dlsym(ewk_handle, "ewk_frame_selection_right_set");
2227         int ewkX, ewkY;
2228         _coords_evas_to_ewk(webview, x, y, &ewkX, &ewkY);
2229         if (sd->ewk_frame_selection_right_set(sd->ewk_view_frame_main_get(webview), ewkX, ewkY,
2230                  &back->x, &back->y, &back->h)) {
2231              _coords_ewk_to_evas(webview, back->x, back->y, &back->x, &back->y);
2232              _text_selection_set_back_info(sd, back->x, back->y, back->h);
2233         }
2234      }
2235 }
2236
2237 static void
2238 _text_selection_move_by(Smart_Data *sd, int dx, int dy)
2239 {
2240    _text_selection_set_front_info(sd, sd->text_selection.front.x + dx,
2241          sd->text_selection.front.y + dy,
2242          sd->text_selection.front.h);
2243    _text_selection_set_back_info(sd, sd->text_selection.back.x + dx,
2244          sd->text_selection.back.y + dy,
2245          sd->text_selection.back.h);
2246 }
2247 // minimap
2248 static void
2249 _minimap_update_detail(Evas_Object* minimap, Smart_Data *sd, cairo_surface_t* src, int srcW, int srcH, Eina_Rectangle* visibleRect)
2250 {
2251    void* pixels;
2252    cairo_t* cr;
2253    cairo_surface_t* dest;
2254    cairo_status_t status;
2255
2256    if (!sd->cairo_surface_status)
2257      sd->cairo_surface_status = (cairo_status_t (*)(cairo_surface_t *))dlsym(cairo_handle, "cairo_surface_status");
2258    if (!sd->cairo_image_surface_create_for_data)
2259      sd->cairo_image_surface_create_for_data = (cairo_surface_t * (*)(unsigned char *, cairo_format_t, int, int, int))dlsym(cairo_handle, "cairo_image_surface_create_for_data");
2260
2261    //TODO: check which one is faster
2262    //      1) reuse minimap
2263    //      2) recreate evas_object and set pixel
2264    evas_object_image_size_set(minimap, srcW, srcH);
2265    evas_object_image_fill_set(minimap, 0, 0, srcW, srcH);
2266    evas_object_resize(minimap, srcW, srcH);
2267
2268    pixels = evas_object_image_data_get(minimap, 1);
2269    dest = sd->cairo_image_surface_create_for_data(
2270          (unsigned char*)pixels, CAIRO_FORMAT_RGB24, srcW, srcH, srcW * 4);
2271    status = sd->cairo_surface_status(dest);
2272    if (status != CAIRO_STATUS_SUCCESS)
2273      {
2274         printf("[%s] fail to create cairo surface\n", __func__);
2275         goto error_cairo_surface;
2276      }
2277
2278    if (!sd->cairo_create)
2279      sd->cairo_create = (cairo_t * (*)(cairo_surface_t *))dlsym(cairo_handle, "cairo_create");
2280    cr = sd->cairo_create(dest);
2281    status = sd->cairo_surface_status(dest);
2282    if (status != CAIRO_STATUS_SUCCESS)
2283      {
2284         printf("[%s] fail to create cairo\n", __func__);
2285         goto error_cairo;
2286      }
2287
2288    if (!sd->cairo_set_source_surface)
2289      sd->cairo_set_source_surface = (void (*)(cairo_t *, cairo_surface_t *, double, double))dlsym(cairo_handle, "cairo_set_source_surface");
2290    if (!sd->cairo_paint)
2291      sd->cairo_paint = (void (*)(cairo_t *))dlsym(cairo_handle, "cairo_paint");
2292    if (!sd->cairo_set_source_rgb)
2293      sd->cairo_set_source_rgb = (void (*)(cairo_t *, double, double, double))dlsym(cairo_handle, "cairo_set_source_rgb");
2294    if (!sd->cairo_rectangle)
2295      sd->cairo_rectangle = (void (*)(cairo_t *, double, double, double, double))dlsym(cairo_handle, "cairo_rectangle");
2296    if (!sd->cairo_set_line_width)
2297      sd->cairo_set_line_width = (void (*)(cairo_t *, double))dlsym(cairo_handle, "cairo_set_line_width");
2298    if (!sd->cairo_stroke)
2299      sd->cairo_stroke = (void (*)(cairo_t *cr))dlsym(cairo_handle, "cairo_stroke"); 
2300    if (!sd->cairo_set_antialias)
2301      sd->cairo_set_antialias = (void (*)(cairo_t *, cairo_antialias_t))dlsym(cairo_handle, "cairo_set_antialias");
2302
2303    sd->cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
2304    sd->cairo_set_source_surface(cr, src, 0, 0);
2305    sd->cairo_paint(cr);
2306    sd->cairo_set_source_rgb(cr, 0, 0, 255);
2307    sd->cairo_set_line_width(cr, 1);
2308    sd->cairo_rectangle(cr,
2309          visibleRect->x, visibleRect->y, visibleRect->w, visibleRect->h);
2310    sd->cairo_stroke(cr);
2311
2312    if (!sd->cairo_destroy)
2313      sd->cairo_destroy = (void (*)(cairo_t *))dlsym(cairo_handle, "cairo_destroy");
2314    sd->cairo_destroy(cr);
2315
2316 error_cairo:
2317    if (!sd->cairo_surface_destroy)
2318      sd->cairo_surface_destroy = (void (*)(cairo_surface_t *))dlsym(cairo_handle, "cairo_surface_destroy");
2319    sd->cairo_surface_destroy(dest);
2320 error_cairo_surface:
2321    evas_object_image_data_set(minimap, pixels);
2322    return;
2323 }
2324
2325 static void
2326 _minimap_update(Evas_Object* minimap, Smart_Data *sd, cairo_surface_t* src, int minimapW, int minimapH)
2327 {
2328    if (minimap == NULL || src == NULL) return;
2329    Evas_Object *webview = sd->base.self;
2330
2331    if (!sd->ewk_view_frame_main_get)
2332      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
2333
2334    if (!sd->ewk_frame_contents_size_get)
2335      sd->ewk_frame_contents_size_get = (Eina_Bool (*)(const Evas_Object *, Evas_Coord *, Evas_Coord *))dlsym(ewk_handle, "ewk_frame_contents_size_get");
2336    int cw, ch;
2337    sd->ewk_frame_contents_size_get(sd->ewk_view_frame_main_get(webview), &cw, &ch);
2338    if (cw == 0 || ch == 0) return;
2339
2340    if (!sd->ewk_frame_visible_content_geometry_get)
2341      sd->ewk_frame_visible_content_geometry_get = (Eina_Bool (*)(const Evas_Object *, Eina_Bool, int *, int *, int *, int *))dlsym(ewk_handle, "ewk_frame_visible_content_geometry_get");
2342    int x, y, w, h;
2343    sd->ewk_frame_visible_content_geometry_get(
2344          sd->ewk_view_frame_main_get(webview), EINA_FALSE,
2345          &x, &y, &w, &h);
2346    DBG("visible area : %d, %d, %d, %d\n", x, y, w, h);
2347
2348    Eina_Rectangle rect = {
2349         x * minimapW / cw, y * minimapH / ch,
2350         w * minimapW / cw, h * minimapH / ch};
2351    _minimap_update_detail(minimap, sd, src, minimapW, minimapH, &rect);
2352 }
2353
2354 static cairo_surface_t*
2355 _image_clone_get(Smart_Data *sd, int* minimap_w, int* minimap_h)
2356 {
2357    DBG("%s is called\n", __func__);
2358    Evas_Object *webview = sd->base.self;
2359    EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, NULL);
2360
2361    if (!sd->ewk_view_frame_main_get)
2362      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
2363
2364    if (!sd->ewk_frame_contents_size_get)
2365      sd->ewk_frame_contents_size_get = (Eina_Bool (*)(const Evas_Object *, Evas_Coord *, Evas_Coord *))dlsym(ewk_handle, "ewk_frame_contents_size_get");
2366    int w, h;
2367    sd->ewk_frame_contents_size_get(sd->ewk_view_frame_main_get(webview), &w, &h);
2368    printf(" W : %d / H : %d\n", w, h);
2369
2370    float x_scale = MINIMAP_WIDTH / (float)w;
2371    float y_scale = MINIMAP_HEIGHT / (float)h;
2372    float scale_factor;
2373    if (x_scale < y_scale)
2374      {
2375         scale_factor = x_scale;
2376         *minimap_w = MINIMAP_WIDTH;
2377         *minimap_h = h * scale_factor;
2378      }
2379    else
2380      {
2381         scale_factor = y_scale;
2382         *minimap_w = w * scale_factor;
2383         *minimap_h = MINIMAP_HEIGHT;
2384      }
2385    printf(" minimap w,h : (%d, %d)\n", *minimap_w, *minimap_h);
2386
2387    if (!sd->ewk_view_paint_contents)
2388      sd->ewk_view_paint_contents = (Eina_Bool (*)(Ewk_View_Private_Data *, cairo_t *, const Eina_Rectangle *))dlsym(ewk_handle, "ewk_view_paint_contents");
2389    if (!sd->cairo_image_surface_create)
2390      sd->cairo_image_surface_create = (cairo_surface_t * (*)(cairo_format_t, int, int))dlsym(cairo_handle, "cairo_image_surface_create");
2391    if (!sd->cairo_create)
2392      sd->cairo_create = (cairo_t * (*)(cairo_surface_t *))dlsym(cairo_handle, "cairo_create");
2393    if (!sd->cairo_destroy)
2394      sd->cairo_destroy = (void (*)(cairo_t *))dlsym(cairo_handle, "cairo_destroy");
2395    if (!sd->cairo_scale)
2396      sd->cairo_scale = (void (*)(cairo_t *, double, double))dlsym(cairo_handle, "cairo_scale");
2397    if (!sd->cairo_surface_write_to_png)
2398      sd->cairo_surface_write_to_png = (cairo_status_t (*)(cairo_surface_t *, const char *))dlsym(cairo_handle, "cairo_surface_write_to_png");
2399    if (!sd->cairo_set_antialias)
2400      sd->cairo_set_antialias = (void (*)(cairo_t *, cairo_antialias_t))dlsym(cairo_handle, "cairo_set_antialias");
2401
2402    cairo_surface_t* ret = sd->cairo_image_surface_create(CAIRO_FORMAT_RGB24, *minimap_w, *minimap_h);
2403    cairo_t* cr = sd->cairo_create(ret);
2404    sd->cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
2405    sd->cairo_scale(cr, scale_factor, scale_factor);
2406    Eina_Rectangle rect = {0, 0, w, h};
2407    sd->ewk_view_paint_contents(priv, cr, &rect);
2408    sd->cairo_destroy(cr);
2409    sd->cairo_surface_write_to_png(ret, "/home/root/test.png");
2410
2411    return ret;
2412 }
2413
2414 // coord
2415 static void
2416 _unzoom_position(Evas_Object* obj, int x, int y, int* ux, int* uy)
2417 {
2418    INTERNAL_ENTRY;
2419    int viewY;
2420    evas_object_geometry_get(obj, NULL, &viewY, NULL, NULL);
2421
2422    if (!sd->ewk_view_zoom_get)
2423      sd->ewk_view_zoom_get = (float (*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_zoom_get");
2424    float zoomRatio = sd->ewk_view_zoom_get(obj);
2425    if (zoomRatio)
2426      {
2427         *ux = x / zoomRatio;
2428         *uy = (y - viewY) / zoomRatio;
2429      }
2430 }
2431
2432 static void
2433 _coords_evas_to_ewk(Evas_Object* obj, int x, int y, int* ux, int* uy)
2434 {
2435    INTERNAL_ENTRY;
2436
2437    if (!sd->ewk_view_frame_main_get)
2438      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
2439
2440    if (!sd->ewk_frame_scroll_pos_get)
2441      sd->ewk_frame_scroll_pos_get = (Eina_Bool (*)(const Evas_Object *, int *, int *))dlsym(ewk_handle, "ewk_frame_scroll_pos_get");
2442
2443    int scrollX, scrollY, viewY;
2444    sd->ewk_frame_scroll_pos_get(sd->ewk_view_frame_main_get(obj), &scrollX, &scrollY);
2445    evas_object_geometry_get(obj, NULL, &viewY, NULL, NULL);
2446    *ux = x + scrollX;
2447    *uy = y + scrollY - viewY;
2448 }
2449
2450 static void
2451 _coords_ewk_to_evas(Evas_Object* obj, int x, int y, int* ux, int* uy)
2452 {
2453    INTERNAL_ENTRY;
2454
2455    if (!sd->ewk_view_frame_main_get)
2456      sd->ewk_view_frame_main_get = (Evas_Object *(*)(const Evas_Object *))dlsym(ewk_handle, "ewk_view_frame_main_get");
2457
2458    if (!sd->ewk_frame_scroll_pos_get)
2459      sd->ewk_frame_scroll_pos_get = (Eina_Bool (*)(const Evas_Object *, int *, int *))dlsym(ewk_handle, "ewk_frame_scroll_pos_get");
2460
2461    int scrollX, scrollY, viewY;
2462    sd->ewk_frame_scroll_pos_get(sd->ewk_view_frame_main_get(obj), &scrollX, &scrollY);
2463    evas_object_geometry_get(obj, NULL, &viewY, NULL, NULL);
2464    *ux = x - scrollX;
2465    *uy = y - scrollY + viewY;
2466 }
2467 #endif