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