9382dbdfd72977716e8654d26fc43d04d6f1174c
[platform/core/uifw/dali-adaptor.git] / adaptors / mobile / evas-plugin-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "evas-plugin-impl.h"
20
21 // EXTERNAL HEADERS
22 #include <dali/public-api/dali-core.h>
23 #include <dali/integration-api/debug.h>
24
25 #include <Ecore_IMF_Evas.h>
26
27 // INTERNAL HEADERS
28 #include <accessibility-manager.h>
29 #include <clipboard-event-notifier.h>
30 #include <imf-manager.h>
31
32 #include <adaptor-impl.h>
33 #include "mobile-render-surface-factory.h"
34 #include <pixmap-render-surface.h>
35 #include <trigger-event.h>
36
37 namespace Dali
38 {
39
40 namespace SlpPlatform
41 {
42 class SlpPlatformAbstraction;
43 }
44
45 namespace Integration
46 {
47 class Core;
48 }
49
50 namespace Internal
51 {
52
53 namespace Adaptor
54 {
55
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gEvasPluginLogFilter = Debug::Filter::New(Debug::Verbose, true, "LOG_EVAS_PLUGIN");
58 #endif
59
60 const char * CLIPBOARD_ATOM                = "CBHM_MSG";
61 const char * CLIPBOARD_SET_OWNER_MESSAGE   = "SET_OWNER";
62
63 /**
64  * Evas_Modifier enums in Ecore_Input.h do not match Ecore_Event_Modifier in Ecore_Input.h.
65  * This function converts from Evas_Modifier to Ecore_Event_Modifier enums.
66  * @param[in] evasModifier the Evas_Modifier input.
67  * @return the Ecore_Event_Modifier output.
68  */
69 unsigned int EvasModifierToEcoreModifier(Evas_Modifier* evasModifier)
70 {
71    Eina_Bool control, alt, shift, altGr, win;
72
73    control = evas_key_modifier_is_set(evasModifier, "Control");
74    alt = evas_key_modifier_is_set(evasModifier, "Alt");
75    shift = evas_key_modifier_is_set(evasModifier, "Shift");
76    altGr = evas_key_modifier_is_set(evasModifier, "AltGr");
77    win = evas_key_modifier_is_set(evasModifier, "Win");
78    win = evas_key_modifier_is_set(evasModifier, "Super");
79    win = evas_key_modifier_is_set(evasModifier, "Hyper");
80
81    unsigned int modifier( 0 );  // If no other matches returns NONE.
82
83    if ( shift )
84    {
85      modifier |= ECORE_EVENT_MODIFIER_SHIFT;  // enums from ecore_imf/ecore_imf.h
86    }
87
88    if ( alt )
89    {
90      modifier |= ECORE_EVENT_MODIFIER_ALT;
91    }
92
93    if ( control )
94    {
95      modifier |= ECORE_EVENT_MODIFIER_CTRL;
96    }
97
98    if ( win )
99    {
100      modifier |= ECORE_EVENT_MODIFIER_WIN;
101    }
102
103    if ( altGr )
104    {
105      modifier |= ECORE_EVENT_MODIFIER_ALTGR;
106    }
107
108    return modifier;
109 }
110
111 static void _evas_object_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
112 {
113   EvasPlugin* ep = (EvasPlugin*)data;
114   if(ep)
115   {
116     Evas_Event_Mouse_Down* ev;
117     ev = (Evas_Event_Mouse_Down *)event_info;
118
119     Evas_Coord rel_x, rel_y;
120     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
121     evas_object_geometry_get(obj, &obj_x,  &obj_y, &obj_w, &obj_h);
122
123     rel_x = ev->canvas.x - obj_x;
124     rel_y = ev->canvas.y - obj_y;
125
126     // create dali TouchEvent & SendEvent
127     TouchPoint point(0, TouchPoint::Down, rel_x, rel_y);
128     ep->OnTouchEvent(point, ev->timestamp);
129   }
130 }
131
132 static void _evas_object_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
133 {
134   EvasPlugin* ep = (EvasPlugin*)data;
135   if(ep)
136   {
137     Evas_Event_Mouse_Move *ev;
138     ev = (Evas_Event_Mouse_Move *)event_info;
139
140     Evas_Coord rel_x, rel_y;
141     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
142     evas_object_geometry_get(obj, &obj_x,  &obj_y, &obj_w, &obj_h);
143
144     rel_x = ev->cur.canvas.x - obj_x;
145     rel_y = ev->cur.canvas.y - obj_y;
146
147     // create dali TouchEvent & SendEvent
148     TouchPoint point(0, TouchPoint::Motion, rel_x, rel_y);
149     ep->OnTouchEvent(point, ev->timestamp);
150   }
151 }
152
153 static void _evas_object_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
154 {
155   EvasPlugin* ep = (EvasPlugin*)data;
156   if(ep)
157   {
158     Evas_Event_Mouse_Up *ev;
159     ev = (Evas_Event_Mouse_Up *)event_info;
160
161     Evas_Coord rel_x, rel_y;
162     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
163     evas_object_geometry_get(obj, &obj_x,  &obj_y, &obj_w, &obj_h);
164
165     rel_x = ev->canvas.x - obj_x;
166     rel_y = ev->canvas.y - obj_y;
167
168     // create dali TouchEvent & SendEvent
169     TouchPoint point(0, TouchPoint::Up, rel_x, rel_y);
170     ep->OnTouchEvent(point, ev->timestamp);
171   }
172 }
173
174 static void _evas_object_mouse_wheel_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
175 {
176   EvasPlugin* ep = (EvasPlugin*)data;
177   if(ep)
178   {
179     Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*)event_info;
180     Evas_Coord rel_x, rel_y;
181     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
182     evas_object_geometry_get(obj, &obj_x,  &obj_y, &obj_w, &obj_h);
183
184     rel_x = ev->canvas.x - obj_x;
185     rel_y = ev->canvas.y - obj_y;
186
187     MouseWheelEvent wheelEvent(ev->direction, -1 /*Need to check evas modifier*/, Vector2(rel_x, rel_y), ev->z, ev->timestamp);
188     ep->OnMouseWheelEvent(wheelEvent);
189   }
190 }
191
192 static void _evas_object_multi_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
193 {
194   EvasPlugin* ep = (EvasPlugin*)data;
195   if(ep)
196   {
197     Evas_Event_Multi_Down *ev = (Evas_Event_Multi_Down*)event_info;
198
199     Evas_Coord rel_x, rel_y;
200     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
201     evas_object_geometry_get(obj, &obj_x,  &obj_y, &obj_w, &obj_h);
202
203     rel_x = ev->canvas.x - obj_x;
204     rel_y = ev->canvas.y - obj_y;
205
206     // create dali TouchEvent & SendEvent
207     TouchPoint point(ev->device, TouchPoint::Down, rel_x, rel_y);
208     ep->OnTouchEvent(point, ev->timestamp);
209   }
210 }
211
212 static void _evas_object_multi_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
213 {
214   EvasPlugin* ep = (EvasPlugin*)data;
215   if(ep)
216   {
217     Evas_Event_Multi_Up *ev = (Evas_Event_Multi_Up*)event_info;
218
219     Evas_Coord rel_x, rel_y;
220     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
221     evas_object_geometry_get(obj, &obj_x,  &obj_y, &obj_w, &obj_h);
222
223     rel_x = ev->canvas.x - obj_x;
224     rel_y = ev->canvas.y - obj_y;
225
226     // create dali TouchEvent & SendEvent
227     TouchPoint point(ev->device, TouchPoint::Up, rel_x, rel_y);
228     ep->OnTouchEvent(point, ev->timestamp);
229   }
230 }
231 static void _evas_object_multi_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
232 {
233   EvasPlugin* ep = (EvasPlugin*)data;
234   if(ep)
235   {
236     Evas_Event_Multi_Move *ev = (Evas_Event_Multi_Move*)event_info;
237
238     Evas_Coord rel_x, rel_y;
239     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
240     evas_object_geometry_get(obj, &obj_x,  &obj_y, &obj_w, &obj_h);
241
242     rel_x = ev->cur.canvas.x - obj_x;
243     rel_y = ev->cur.canvas.y - obj_y;
244
245     // create dali TouchEvent & SendEvent
246     TouchPoint point(ev->device, TouchPoint::Motion, rel_x, rel_y);
247     ep->OnTouchEvent(point, ev->timestamp);
248   }
249 }
250
251 static void _evas_object_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
252 {
253   EvasPlugin* ep = (EvasPlugin*)data;
254
255   if(ep)
256   {
257     Evas_Event_Key_Down* keyEvent( (Evas_Event_Key_Down*)event_info );
258     bool eventHandled( false );
259
260     if(!keyEvent->keyname)
261     {
262       return;
263     }
264
265     Ecore_IMF_Context* imfContext = NULL;
266     if ( Dali::Adaptor::IsAvailable() )
267     {
268       Dali::ImfManager imfManager = Dali::ImfManager::Get();
269       if ( imfManager )
270       {
271         imfContext = reinterpret_cast<Ecore_IMF_Context*>( imfManager.GetContext() );
272       }
273     }
274
275     // XF86Stop and XF86Send must skip ecore_imf_context_filter_event.
276     if ( imfContext && strcmp( keyEvent->keyname, "XF86Send" ) && strcmp( keyEvent->keyname, "XF86Phone" ) && strcmp( keyEvent->keyname, "XF86Stop" ) )
277     {
278       Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
279       ecore_imf_evas_event_key_down_wrap(keyEvent, &ecoreKeyDownEvent);
280
281       eventHandled = ecore_imf_context_filter_event(imfContext,
282                                                       ECORE_IMF_EVENT_KEY_DOWN,
283                                                      (Ecore_IMF_Event *) &ecoreKeyDownEvent );
284
285       // If the event has not been handled by IMF then check if we should reset our IMF context
286       if( !eventHandled )
287       {
288         if ( !strcmp( keyEvent->keyname, "Escape"   ) ||
289              !strcmp( keyEvent->keyname, "Return"   ) ||
290              !strcmp( keyEvent->keyname, "KP_Enter" ) )
291         {
292           ecore_imf_context_reset( imfContext );
293        }
294       }
295     }
296
297     // If the event wasn't handled then we should send a key event.
298     if ( !eventHandled )
299     {
300       std::string keyName( keyEvent->keyname );
301       std::string keyString( "" );
302       int keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
303       int modifier( EvasModifierToEcoreModifier ( keyEvent->modifiers ) );
304       unsigned long time( keyEvent->timestamp );
305
306       // Ensure key event string is not NULL as keys like SHIFT have a null string.
307       if ( keyEvent->string )
308       {
309         keyString = keyEvent->string;
310       }
311
312       KeyEvent daliKeyEvent(keyName, keyString, keyCode, modifier, time, KeyEvent::Down);
313       ep->OnKeyEvent( daliKeyEvent );
314     }
315   }
316 }
317
318 static void _evas_object_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
319 {
320   EvasPlugin* ep = (EvasPlugin*)data;
321   if(ep)
322   {
323     // We're consuming key up event so we have to pass to IMF so that it can parse it as well.
324     Evas_Event_Key_Up* keyEvent( (Evas_Event_Key_Up*)event_info );
325     bool eventHandled( false );
326
327     Ecore_IMF_Context* imfContext = NULL;
328     if ( Dali::Adaptor::IsAvailable() )
329     {
330       Dali::ImfManager imfManager = Dali::ImfManager::Get();
331       if ( imfManager )
332       {
333         imfContext = reinterpret_cast<Ecore_IMF_Context*>( imfManager.GetContext() );
334       }
335     }
336
337     if ( imfContext && strcmp( keyEvent->keyname, "XF86Send" ) && strcmp( keyEvent->keyname, "XF86Phone" ) && strcmp( keyEvent->keyname, "XF86Stop" ))
338     {
339       Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
340       ecore_imf_evas_event_key_up_wrap(keyEvent, &ecoreKeyUpEvent);
341
342       eventHandled = ecore_imf_context_filter_event( imfContext,
343                                       ECORE_IMF_EVENT_KEY_UP,
344                                       (Ecore_IMF_Event *) &ecoreKeyUpEvent );
345     }
346
347     if ( !eventHandled )
348     {
349       std::string keyName( keyEvent->keyname );
350       std::string keyString( "" );
351       int keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
352       int modifier( EvasModifierToEcoreModifier ( keyEvent->modifiers ) );
353       unsigned long time( keyEvent->timestamp );
354
355       // Ensure key event string is not NULL as keys like SHIFT have a null string.
356       if ( keyEvent->string )
357       {
358         keyString = keyEvent->string;
359       }
360
361       KeyEvent daliKeyEvent(keyName, keyString, keyCode, modifier, time, KeyEvent::Up);
362       ep->OnKeyEvent( daliKeyEvent );
363     }
364   }
365 }
366
367 static void _evas_object_focus_in_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
368 {
369   EvasPlugin* ep = (EvasPlugin*)data;
370   if(ep != NULL && ep->GetEvasImageObject() == obj)
371   {
372     ep->OnEvasObjectFocusedIn();
373   }
374 }
375
376 static void _evas_object_focus_out_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
377 {
378   EvasPlugin* ep = (EvasPlugin*)data;
379   if(ep != NULL && ep->GetEvasImageObject() == obj)
380   {
381     ep->OnEvasObjectFocusedOut();
382   }
383 }
384
385 static void _elm_focus_object_focus_in_cb(void *data, Evas_Object *obj, void *event_info)
386 {
387   EvasPlugin* ep = (EvasPlugin*)data;
388   if(ep != NULL && ep->GetElmFocusObject() == obj)
389   {
390     Evas_Object* win = elm_object_top_widget_get(obj);
391     if(strcmp("elm_win", elm_object_widget_type_get(win)) == 0)
392     {
393       if(elm_win_focus_highlight_enabled_get(win) == EINA_TRUE)
394       {
395         // To allow that KeyboardFocusManager can handle the keyboard focus
396         KeyEvent fakeKeyEvent("", "", 0, 0, 100 /* fake timestamp */, KeyEvent::Down);
397         ep->OnKeyEvent( fakeKeyEvent );
398       }
399     }
400     else
401     {
402       DALI_LOG_ERROR("It is not elm win\n");
403     }
404
405     evas_object_focus_set(ep->GetEvasImageObject(), EINA_TRUE);
406   }
407 }
408
409 static void _elm_focus_object_focus_out_cb(void *data, Evas_Object *obj, void *event_info)
410 {
411   EvasPlugin* ep = (EvasPlugin*)data;
412   if(ep != NULL && ep->GetElmFocusObject() == obj)
413   {
414     evas_object_focus_set(ep->GetEvasImageObject(), EINA_FALSE);
415   }
416 }
417
418 static void _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
419 {
420   EvasPlugin* ep = (EvasPlugin*)data;
421   if(ep != NULL && ep->GetEvasImageObject() == evas_focus_get(e))
422   {
423     ep->OnEvasObjectFocusedIn();
424   }
425 }
426
427 static void _canvas_focus_out_cb(void *data, Evas *e, void *event_info)
428 {
429   EvasPlugin* ep = (EvasPlugin*)data;
430   if(ep != NULL && ep->GetEvasImageObject() == evas_focus_get(e))
431   {
432     ep->OnEvasObjectFocusedOut();
433   }
434 }
435
436 static void _evas_object_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
437 {
438   EvasPlugin* ep = (EvasPlugin*)data;
439   if(ep)
440   {
441     ep->Move();
442   }
443 }
444
445 static void _evas_object_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
446 {
447   EvasPlugin* ep = (EvasPlugin*)data;
448   if(ep)
449   {
450     ep->Resize();
451   }
452 }
453
454 static void _evas_render_post_cb(void *data, Evas *e, void *event_info)
455 {
456   EvasPlugin* ep = (EvasPlugin*)data;
457   if(ep)
458   {
459     // call RenderSync when the window surface(onscreen) was presented to LCD.
460     ep->RenderSync();
461
462     //After first render emit signal to notify
463     if(!ep->mFirstRenderCompleteNotified)
464     {
465       ep->OnFirstRenderCompleted();
466     }
467   }
468 }
469
470 /*
471  * When the evas plugin is resumed,
472  * need to forcely dirty set the evas object on idle time to show again the result of dali rendering.
473  * One time should be enough.
474  */
475 static Eina_Bool _evas_object_dirty_set_idle_cb(void *data)
476 {
477   EvasPlugin* ep = (EvasPlugin*)data;
478
479   if(ep)
480   {
481     Evas_Object* eo = ep->GetEvasImageObject();
482     if(eo)
483     {
484       /* dirty set to post the result of rendering via evas */
485       evas_object_image_pixels_dirty_set(eo, EINA_TRUE);
486     }
487
488     ep->ClearIdler(false); // clear idler handle without deleting handle. because handle will be deleted by ecore
489   }
490
491   // we need it once.
492   return ECORE_CALLBACK_CANCEL;
493 }
494
495 static Eina_Bool _elm_access_highlight_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
496 {
497   EvasPlugin* ep = (EvasPlugin*)data;
498   bool ret = false;
499
500   if(ep && actionInfo)
501   {
502     // action_by has NEXT or PREV
503     if (actionInfo->action_by == ELM_ACCESS_ACTION_HIGHLIGHT_NEXT)
504     {
505       ret = ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, actionInfo);
506       DALI_LOG_INFO(gEvasPluginLogFilter, Debug::General, "[%s:%d] Next returns %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
507     }
508     else if (actionInfo->action_by == ELM_ACCESS_ACTION_HIGHLIGHT_PREV)
509     {
510       ret = ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_HIGHLIGHT_PREV, actionInfo);
511       DALI_LOG_INFO(gEvasPluginLogFilter, Debug::General, "[%s:%d] Prev returns %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
512     }
513     else
514     {
515       /*
516         * In case of access over, action_by has ELM_ACCESS_ACTION_HIGHLIGHT
517         * real operation will be done in _elm_access_over_cb
518         * so just return true in order to remove the entire focus indicator
519         */
520
521       /*
522         * Even if action_by has intialized value (-1), highlight action is valid
523         */
524       ret = true;
525     }
526   }
527   else
528   {
529     DALI_LOG_WARNING("[%s:%d] has no actionInfo\n", __FUNCTION__, __LINE__);
530   }
531
532   return ret;
533 }
534
535 static Eina_Bool _elm_access_read_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
536 {
537   EvasPlugin* ep = (EvasPlugin*)data;
538   bool ret = false;
539
540   if(ep)
541   {
542     PositionSize geometry = ep->GetEvasObjectGeometry();
543
544     if(actionInfo)
545     {
546       ret = ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_READ, actionInfo, (actionInfo->x - geometry.x), (actionInfo->y - geometry.y));
547       DALI_LOG_INFO(gEvasPluginLogFilter, Debug::General, "[%s:%d] returns %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
548     }
549     else
550     {
551       DALI_LOG_WARNING( "[%s:%d] has no actionInfo\n", __FUNCTION__, __LINE__);
552     }
553   }
554
555   return ret;
556 }
557
558 static Eina_Bool _elm_access_over_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
559 {
560   EvasPlugin* ep = (EvasPlugin*)data;
561   bool ret = false;
562
563   if(ep)
564   {
565     PositionSize geometry = ep->GetEvasObjectGeometry();
566
567     if(actionInfo)
568     {
569       ret = ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_OVER, actionInfo, (actionInfo->x - geometry.x), (actionInfo->y - geometry.y));
570       DALI_LOG_INFO(gEvasPluginLogFilter, Debug::General, "[%s:%d] returns %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
571     }
572     else
573     {
574       DALI_LOG_WARNING( "[%s:%d] has no actionInfo\n", __FUNCTION__, __LINE__);
575     }
576   }
577
578   return ret;
579 }
580
581 static Eina_Bool _elm_access_highlight_next_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
582 {
583   EvasPlugin* ep = (EvasPlugin*)data;
584   return ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, actionInfo);
585 }
586
587 static Eina_Bool _elm_access_highlight_prev_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
588 {
589   EvasPlugin* ep = (EvasPlugin*)data;
590   return ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_HIGHLIGHT_PREV, actionInfo);
591 }
592
593 static Eina_Bool _elm_access_activate_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
594 {
595   EvasPlugin* ep = (EvasPlugin*)data;
596   return ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_ACTIVATE, actionInfo);
597 }
598
599 static Eina_Bool _elm_access_unhighlight_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
600 {
601   EvasPlugin* ep = (EvasPlugin*)data;
602   return ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_UNHIGHLIGHT, actionInfo);
603 }
604
605 static Eina_Bool _elm_access_back_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
606 {
607   EvasPlugin* ep = (EvasPlugin*)data;
608   return ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_BACK, actionInfo);
609 }
610
611 static Eina_Bool _elm_access_value_up_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
612 {
613   EvasPlugin* ep = (EvasPlugin*)data;
614   return ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_UP, actionInfo);
615 }
616
617 static Eina_Bool _elm_access_value_down_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
618 {
619   EvasPlugin* ep = (EvasPlugin*)data;
620   return ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_DOWN, actionInfo);
621 }
622
623 static Eina_Bool _elm_access_scroll_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
624 {
625   EvasPlugin* ep = (EvasPlugin*)data;
626   bool ret = false;
627
628   if(actionInfo && ep)
629   {
630     Evas_Coord rel_x, rel_y;
631     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
632     Evas_Object* eo = ep->GetEvasImageObject();
633
634     if(eo)
635     {
636       evas_object_geometry_get(eo, &obj_x,  &obj_y, &obj_w, &obj_h);
637
638       rel_x = actionInfo->x - obj_x;
639       rel_y = actionInfo->y - obj_y;
640
641       ret = ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_SCROLL, actionInfo, rel_x, rel_y);
642     }
643   }
644   else
645   {
646     DALI_LOG_WARNING("[%s:%d] has no actionInfo\n", __FUNCTION__, __LINE__);
647   }
648
649   return ret;
650 }
651
652 static Eina_Bool _elm_access_mouse_cb(void *data, Evas_Object *obj, Elm_Access_Action_Info *actionInfo)
653 {
654   EvasPlugin* ep = (EvasPlugin*)data;
655   bool ret = false;
656
657   if(actionInfo && ep)
658   {
659     Evas_Coord rel_x, rel_y;
660     Evas_Coord obj_x,  obj_y, obj_w, obj_h;
661     Evas_Object* eo = ep->GetEvasImageObject();
662
663     if(eo)
664     {
665       evas_object_geometry_get(eo, &obj_x,  &obj_y, &obj_w, &obj_h);
666
667       rel_x = actionInfo->x - obj_x;
668       rel_y = actionInfo->y - obj_y;
669
670       ret = ep->OnAccessibilityActionEvent(ELM_ACCESS_ACTION_MOUSE, actionInfo, rel_x, rel_y);
671     }
672   }
673   else
674   {
675     DALI_LOG_WARNING("[%s:%d] has no actionInfo\n", __FUNCTION__, __LINE__);
676   }
677
678   return ret;
679 }
680
681 static Eina_Bool _ecore_x_event_selection_clear(void *data, int type, void *event)
682 {
683   EvasPlugin* ep = (EvasPlugin*)data;
684
685   if( ep )
686   {
687     ep->OnEcoreEventSelectionCleared(data, type, event);
688   }
689
690   return ECORE_CALLBACK_PASS_ON;
691 }
692
693 static Eina_Bool _ecore_x_event_selection_notify(void *data, int type, void *event)
694 {
695   EvasPlugin* ep = (EvasPlugin*)data;
696
697   if( ep )
698   {
699     ep->OnEcoreEventSelectionNotified(data, type, event);
700   }
701
702   return ECORE_CALLBACK_PASS_ON;
703 }
704 static Eina_Bool _ecore_x_event_client_message(void* data, int type, void* event)
705 {
706   EvasPlugin* ep = (EvasPlugin*)data;
707
708   if( ep )
709   {
710     ep->OnEcoreEventClientMessaged(data, type, event);
711   }
712
713   return ECORE_CALLBACK_PASS_ON;
714 }
715
716 // Copied from x server
717 static unsigned int GetCurrentMilliSeconds(void)
718 {
719   struct timeval tv;
720
721   struct timespec tp;
722   static clockid_t clockid;
723
724   if (!clockid)
725   {
726 #ifdef CLOCK_MONOTONIC_COARSE
727     if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
728       (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
729     {
730       clockid = CLOCK_MONOTONIC_COARSE;
731     }
732     else
733 #endif
734     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
735     {
736       clockid = CLOCK_MONOTONIC;
737     }
738     else
739     {
740       clockid = ~0L;
741     }
742   }
743   if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
744   {
745     return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
746   }
747
748   gettimeofday(&tv, NULL);
749   return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
750 }
751
752 EvasPlugin::EvasPlugin(Dali::EvasPlugin& evasPlugin, Evas_Object* parent, bool isTransparent, unsigned int initialWidth, unsigned int initialHeight)
753 : mEvasImageObject(NULL),
754   mElmAccessObject(NULL),
755   mElmFocusObject(NULL),
756   mSurface(NULL),
757   mFirstRenderCompleteNotified(false),
758   mEvasPlugin(evasPlugin),
759   mAdaptor(NULL),
760   mEvas(NULL),
761   mEvasImageObjectGeometry(0, 0, initialWidth, initialHeight),
762   mInitialized(false),
763   mIsTransparent(isTransparent),
764   mHasFocus(false),
765   mRenderNotification(NULL),
766   mEvasDirtyIdler(NULL)
767 {
768   DALI_ASSERT_ALWAYS( parent && "No parent object for plugin" );
769   mEvas = AnyCast<Evas*>(evas_object_evas_get(parent));
770
771   /* create evas object image */
772   CreateEvasImageObject(mEvas, initialWidth, initialHeight, isTransparent);
773
774   /* create elm access object */
775   CreateElmAccessObject(parent);
776
777   /* create elm focus object */
778   CreateElmFocusObject(parent);
779
780   /* create adaptor */
781   CreateAdaptor(initialWidth, initialHeight);
782
783   /* render post callback */
784   evas_event_callback_add(mEvas, EVAS_CALLBACK_RENDER_POST, _evas_render_post_cb, this);
785
786   mRenderNotification = new TriggerEvent( boost::bind(&EvasPlugin::Render, this ) );
787
788   mSurface->SetRenderNotification( mRenderNotification );
789
790   mState = Ready;
791 }
792
793 EvasPlugin::~EvasPlugin()
794 {
795   mConnectionTracker.DisconnectAll();
796
797   if (mAdaptor)
798   {
799     Stop();
800
801     // delete idler
802     ClearIdler();
803
804     // no more notifications
805     delete mRenderNotification;
806
807     // delete evas canvas callback for render sync
808     evas_event_callback_del(mEvas, EVAS_CALLBACK_RENDER_POST, _evas_render_post_cb);
809
810     delete mAdaptor;
811     mAdaptor = NULL;
812
813     // delete elm focus object
814     DeleteElmFocusObject();
815
816     // delete elm access object
817     DeleteElmAccessObject();
818
819     // delete evas object image
820     DeleteEvasImageObject();
821
822     if (mSurface)
823     {
824       delete mSurface;
825       mSurface = NULL;
826     }
827   }
828 }
829
830 void EvasPlugin::CreateEvasImageObject(Evas* evas, unsigned int initialWidth, unsigned int initialHeight, bool isTransparent)
831 {
832   /* create evas object */
833
834   mEvasImageObject = evas_object_image_filled_add(mEvas);
835   evas_object_name_set(mEvasImageObject, "dali-evasplugin");
836   evas_object_image_content_hint_set(mEvasImageObject, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
837   evas_object_size_hint_align_set(mEvasImageObject, EVAS_HINT_FILL, EVAS_HINT_FILL);
838   evas_object_size_hint_weight_set(mEvasImageObject, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
839
840   if(isTransparent)
841   {
842     evas_object_image_alpha_set(mEvasImageObject, EINA_TRUE);
843   }
844
845   evas_object_move(mEvasImageObject, 0, 0);
846   evas_object_image_size_set(mEvasImageObject, initialWidth, initialHeight);
847   evas_object_resize(mEvasImageObject, initialWidth, initialHeight);
848
849   /* event callback */
850   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_MOUSE_DOWN, _evas_object_mouse_down_cb, this);
851   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_MOUSE_UP, _evas_object_mouse_up_cb, this);
852   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_MOUSE_MOVE, _evas_object_mouse_move_cb, this);
853   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_MOUSE_WHEEL, _evas_object_mouse_wheel_cb, this);
854
855   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_MULTI_DOWN, _evas_object_multi_down_cb, this);
856   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_MULTI_UP, _evas_object_multi_up_cb, this);
857   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_MULTI_MOVE, _evas_object_multi_move_cb, this);
858
859   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_KEY_DOWN, _evas_object_key_down_cb, this);
860   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_KEY_UP, _evas_object_key_up_cb, this);
861
862   /* move callback */
863   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_MOVE, _evas_object_move_cb, this);
864
865   /* resize callback */
866   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_RESIZE, _evas_object_resize_cb, this);
867
868   /* focus callback */
869   evas_event_callback_add(mEvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, this);
870   evas_event_callback_add(mEvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _canvas_focus_out_cb, this);
871
872   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_FOCUS_IN, _evas_object_focus_in_cb, this);
873   evas_object_event_callback_add(mEvasImageObject, EVAS_CALLBACK_FOCUS_OUT, _evas_object_focus_out_cb, this);
874
875   evas_object_show(mEvasImageObject);
876 }
877
878 void EvasPlugin::DeleteEvasImageObject()
879 {
880   if(mEvasImageObject)
881   {
882     /* event callback */
883     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_MOUSE_DOWN, _evas_object_mouse_down_cb);
884     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_MOUSE_UP, _evas_object_mouse_up_cb);
885     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_MOUSE_MOVE, _evas_object_mouse_move_cb);
886
887     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_MULTI_DOWN, _evas_object_multi_down_cb);
888     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_MULTI_UP, _evas_object_multi_up_cb);
889     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_MULTI_MOVE, _evas_object_multi_move_cb);
890
891     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_KEY_DOWN, _evas_object_key_down_cb);
892     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_KEY_UP, _evas_object_key_up_cb);
893
894     /* move callback */
895     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_MOVE, _evas_object_move_cb);
896
897     /* resize callback */
898     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_RESIZE, _evas_object_resize_cb);
899
900     /* focus callback */
901     evas_event_callback_del(mEvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
902     evas_event_callback_del(mEvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _canvas_focus_out_cb);
903
904     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_FOCUS_IN, _evas_object_focus_in_cb);
905     evas_object_event_callback_del(mEvasImageObject, EVAS_CALLBACK_FOCUS_OUT, _evas_object_focus_out_cb);
906
907     // evas object callbacks are deleted with the object
908     evas_object_del(mEvasImageObject);
909     mEvasImageObject = NULL;
910   }
911 }
912
913 void EvasPlugin::CreateElmAccessObject(Evas_Object* parent)
914 {
915   // elm access register with image object
916   mElmAccessObject = elm_access_object_register(mEvasImageObject, parent);
917
918   // elm access action callbacks
919   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_HIGHLIGHT, _elm_access_highlight_cb, this);
920   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_UNHIGHLIGHT, _elm_access_unhighlight_cb, this);
921   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, _elm_access_highlight_next_cb, this);
922   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_HIGHLIGHT_PREV, _elm_access_highlight_prev_cb, this);
923   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_ACTIVATE, _elm_access_activate_cb, this);
924   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_UP, _elm_access_value_up_cb, this);
925   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_DOWN, _elm_access_value_down_cb, this);
926   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_SCROLL, _elm_access_scroll_cb, this);
927   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_MOUSE, _elm_access_mouse_cb, this);
928   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_BACK, _elm_access_back_cb, this);
929   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_READ, _elm_access_read_cb, this);
930   elm_access_action_cb_set(mElmAccessObject, ELM_ACCESS_ACTION_OVER, _elm_access_over_cb, this);
931
932   /**
933    * Dali doesn't set the order of elm focus chain.
934    * Application should append mElmAccessObject to layout's custom focus chain
935    *
936    * e.g) elm_object_focus_custom_chain_append(parent, mElmAccessObject, NULL);
937    */
938 }
939
940 void EvasPlugin::DeleteElmAccessObject()
941 {
942   if(mElmAccessObject)
943   {
944     // elm access action callbacks and elm_access_object will be deleted in unregister
945     elm_access_object_unregister(mEvasImageObject);
946     mElmAccessObject = NULL;
947   }
948 }
949
950 void EvasPlugin::CreateElmFocusObject(Evas_Object* parent)
951 {
952   // create a button and set style as "focus", if does not want to show the focus, then "transparent"
953   mElmFocusObject = elm_button_add(parent);
954   // don't need to show the focus boundary here
955   elm_object_style_set(mElmFocusObject, "transparent");
956
957   // set the evas image object to focus object, but event should not be propagated
958   elm_object_part_content_set(mElmFocusObject, "elm.swallow.content", mEvasImageObject);
959   evas_object_propagate_events_set(mEvasImageObject, EINA_FALSE);
960
961   // set the evas object you want to make focusable as the content of the swallow part
962   evas_object_size_hint_weight_set(mElmFocusObject, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
963   evas_object_size_hint_align_set(mElmFocusObject, EVAS_HINT_FILL, EVAS_HINT_FILL);
964
965   evas_object_smart_callback_add(mElmFocusObject, "focused", _elm_focus_object_focus_in_cb, this);
966   evas_object_smart_callback_add(mElmFocusObject, "unfocused", _elm_focus_object_focus_out_cb, this);
967
968   evas_object_show(mElmFocusObject);
969 }
970
971 void EvasPlugin::DeleteElmFocusObject()
972 {
973   if(mElmFocusObject)
974   {
975     evas_object_smart_callback_del(mElmFocusObject, "focused", _elm_focus_object_focus_in_cb);
976     evas_object_smart_callback_del(mElmFocusObject, "unfocused", _elm_focus_object_focus_out_cb);
977
978     evas_object_del(mElmFocusObject);
979     mElmFocusObject = NULL;
980   }
981 }
982
983 void EvasPlugin::CreateAdaptor(unsigned int initialWidth, unsigned int initialHeight)
984 {
985   mSurface = CreateSurface(initialWidth, initialHeight);
986
987   mAdaptor = Internal::Adaptor::Adaptor::New( mSurface, DeviceLayout::DEFAULT_BASE_LAYOUT );
988
989   Any surface = mSurface->GetSurface();
990
991   Ecore_X_Pixmap pixmap = AnyCast<Ecore_X_Pixmap>(surface);
992
993   /* set native pixmap surface */
994   Evas_Native_Surface ns;
995   ns.type = EVAS_NATIVE_SURFACE_X11;
996   ns.version = EVAS_NATIVE_SURFACE_VERSION;
997   ns.data.x11.pixmap = pixmap;
998   ns.data.x11.visual = NULL;
999
1000   evas_object_image_native_surface_set(mEvasImageObject, &ns);
1001 }
1002
1003 ECore::RenderSurface* EvasPlugin::CreateSurface( int width, int height )
1004 {
1005   PositionSize pixmapSize( 0, 0, width, height );
1006   Any surface;
1007   Any display;
1008   // if we already have surface, reuse its display
1009   if( mSurface )
1010   {
1011     display = mSurface->GetMainDisplay();
1012   }
1013
1014   // create a X11 pixmap
1015   ECore::RenderSurface* daliSurface = ECore::CreatePixmapSurface( pixmapSize, surface, display, "no name", mIsTransparent );
1016
1017   daliSurface->SetRenderNotification( mRenderNotification );
1018
1019   return daliSurface;
1020 }
1021
1022 void EvasPlugin::ResizeSurface()
1023 {
1024   // remember old surface
1025   Dali::RenderSurface* oldSurface = mSurface;
1026   mSurface = CreateSurface( mEvasImageObjectGeometry.width, mEvasImageObjectGeometry.height );
1027
1028   // ask the replace the surface inside dali
1029   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).ReplaceSurface( *mSurface ); // this method is synchronous => guarantee until rendering next frame
1030
1031   // update the pixmap for evas
1032   {
1033     Any surface = mSurface->GetSurface();
1034     Ecore_X_Pixmap pixmap = AnyCast<Ecore_X_Pixmap>( surface );
1035
1036     Evas_Native_Surface ns;
1037     ns.type = EVAS_NATIVE_SURFACE_X11;
1038     ns.version = EVAS_NATIVE_SURFACE_VERSION;
1039     ns.data.x11.pixmap = pixmap;
1040     ns.data.x11.visual = NULL;
1041
1042     evas_object_image_native_surface_set(mEvasImageObject, &ns);
1043
1044     // its now safe to delete the old surface
1045     delete oldSurface;
1046   }
1047
1048   OnResize();
1049 }
1050
1051 void EvasPlugin::ConnectEcoreEvent()
1052 {
1053   // Get Ecore_Evas using Evas.
1054   Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get( mEvas );
1055
1056   if( ecoreEvas )  // Check invalid or valid.
1057   {
1058     // Get window from Ecore_Evas.
1059     Ecore_X_Window window = ecore_evas_gl_x11_window_get( ecoreEvas );
1060
1061     // Set the application window at ime context.
1062     Dali::ImfManager imfManager = Dali::ImfManager::Get();
1063     Ecore_IMF_Context* imfContext = reinterpret_cast<Ecore_IMF_Context*>( imfManager.GetContext() );
1064     ecore_imf_context_client_window_set( imfContext, reinterpret_cast<void*>( window ) );
1065
1066     if( window )  // Check invalid or valid.
1067     {
1068       // Connect clipboard events.
1069       mEcoreEventHandler.push_back( ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _ecore_x_event_selection_clear, this) );
1070       mEcoreEventHandler.push_back( ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _ecore_x_event_selection_notify, this) );
1071
1072       // Register Client message events - accessibility etc.
1073       mEcoreEventHandler.push_back( ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _ecore_x_event_client_message, this) );
1074     }
1075   }
1076 }
1077
1078 void EvasPlugin::DisconnectEcoreEvent()
1079 {
1080   for( std::vector<Ecore_Event_Handler*>::iterator iter = mEcoreEventHandler.begin(), endIter = mEcoreEventHandler.end(); iter != endIter; ++iter )
1081   {
1082     ecore_event_handler_del( *iter );
1083   }
1084
1085   mEcoreEventHandler.clear();
1086 }
1087
1088 void EvasPlugin::Run()
1089 {
1090   if(mState == Ready)
1091   {
1092     // Run the adaptor
1093     mAdaptor->Start();
1094     mState = Running;
1095
1096     OnInit();
1097   }
1098 }
1099
1100 void EvasPlugin::Pause()
1101 {
1102   if(mState == Running)
1103   {
1104     mAdaptor->Pause();
1105     mState = Suspended;
1106
1107     mPauseSignalV2.Emit( mEvasPlugin );
1108   }
1109 }
1110
1111 void EvasPlugin::Resume()
1112 {
1113   if(mState == Suspended)
1114   {
1115     mAdaptor->Resume();
1116     mState = Running;
1117
1118     mResumeSignalV2.Emit( mEvasPlugin );
1119   }
1120
1121   // forcely dirty_set the evas_object on idle time
1122   ClearIdler();
1123   mEvasDirtyIdler = ecore_idler_add(_evas_object_dirty_set_idle_cb, this);
1124 }
1125
1126 void EvasPlugin::ClearIdler(bool deleteHandle)
1127 {
1128   if(mEvasDirtyIdler)
1129   {
1130     if(deleteHandle)
1131     {
1132       ecore_idler_del(mEvasDirtyIdler);
1133     }
1134     mEvasDirtyIdler = NULL;
1135   }
1136 }
1137
1138 void EvasPlugin::Stop()
1139 {
1140   if(mState != Stopped)
1141   {
1142     // Stop the adaptor
1143     mAdaptor->Stop();
1144     mState = Stopped;
1145
1146     mTerminateSignalV2.Emit( mEvasPlugin );
1147   }
1148 }
1149 Evas_Object* EvasPlugin::GetEvasImageObject()
1150 {
1151   return mEvasImageObject;
1152 }
1153
1154 Evas_Object* EvasPlugin::GetElmAccessObject()
1155 {
1156   return mElmAccessObject;
1157 }
1158
1159 Evas_Object* EvasPlugin::GetElmFocusObject()
1160 {
1161   return mElmFocusObject;
1162 }
1163
1164 void EvasPlugin::OnInit()
1165 {
1166   mInitialized = true;
1167
1168   mInitSignalV2.Emit( mEvasPlugin );
1169 }
1170
1171 void EvasPlugin::OnFirstRenderCompleted()
1172 {
1173   mFirstRenderCompletedSignalV2.Emit( mEvasPlugin );
1174
1175   mFirstRenderCompleteNotified = true;
1176 }
1177
1178 void EvasPlugin::Move()
1179 {
1180   Evas_Coord x, y, w, h;
1181   evas_object_geometry_get(mEvasImageObject, &x, &y, &w, &h);
1182
1183   // update geometry
1184   mEvasImageObjectGeometry.x = x;
1185   mEvasImageObjectGeometry.y = y;
1186   mEvasImageObjectGeometry.width = w;
1187   mEvasImageObjectGeometry.height = h;
1188
1189   DALI_LOG_INFO( gEvasPluginLogFilter, Debug::General, "EvasPlugin::Move : %d, %d, %d x %d\n", x, y, w, h );
1190 }
1191
1192 void EvasPlugin::Resize()
1193 {
1194   Evas_Coord x, y, w, h;
1195   evas_object_geometry_get(mEvasImageObject, &x, &y, &w, &h);
1196
1197   // skip meaningless resize signal
1198   if(w <= 1 || h <= 1)
1199   {
1200     return;
1201   }
1202
1203   if(mEvasImageObjectGeometry.width == w && mEvasImageObjectGeometry.height == h)
1204   {
1205     return;
1206   }
1207
1208   DALI_LOG_INFO( gEvasPluginLogFilter, Debug::General, "old size (%d x %d), new size (%d x %d)\n", mEvasImageObjectGeometry.width, mEvasImageObjectGeometry.height, w, h );
1209
1210   // update geometry
1211   mEvasImageObjectGeometry.x = x;
1212   mEvasImageObjectGeometry.y = y;
1213   mEvasImageObjectGeometry.width = w;
1214   mEvasImageObjectGeometry.height = h;
1215
1216   ResizeSurface();
1217 }
1218
1219 void EvasPlugin::OnResize()
1220 {
1221   if(mInitialized)
1222   {
1223     // emit resized signal to application
1224     mResizeSignalV2.Emit( mEvasPlugin );
1225   }
1226 }
1227
1228 void EvasPlugin::Render()
1229 {
1230   // dirty set while adaptor is running
1231   if( EvasPlugin::Running == mState )
1232   {
1233     /* dirty set to post the result of rendering via evas */
1234     evas_object_image_pixels_dirty_set( mEvasImageObject, EINA_TRUE );
1235   }
1236 }
1237
1238 void EvasPlugin::OnTouchEvent(TouchPoint& point, int timeStamp)
1239 {
1240   if ( mAdaptor )
1241   {
1242     if(timeStamp < 1)
1243     {
1244       timeStamp = GetCurrentMilliSeconds();
1245     }
1246
1247     Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).FeedTouchPoint( point, timeStamp );
1248   }
1249 }
1250
1251 void EvasPlugin::OnKeyEvent(KeyEvent& keyEvent)
1252 {
1253   // Create KeyEvent and send to Core.
1254   if ( mAdaptor )
1255   {
1256     Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).FeedKeyEvent( keyEvent );
1257   }
1258 }
1259
1260 void EvasPlugin::OnMouseWheelEvent(MouseWheelEvent& wheelEvent)
1261 {
1262   if ( mAdaptor )
1263   {
1264     Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).FeedWheelEvent( wheelEvent );
1265   }
1266 }
1267
1268 void EvasPlugin::OnImfActivated(Dali::ImfManager& imfManager)
1269 {
1270   // When imf is activated, set focus to own evas-object to get key events
1271   evas_object_focus_set(mEvasImageObject, EINA_TRUE);
1272 }
1273
1274 void EvasPlugin::RenderSync()
1275 {
1276   if( NULL != mAdaptor )
1277   {
1278     Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).RenderSync();
1279   }
1280 }
1281
1282 bool EvasPlugin::OnAccessibilityActionEvent(Elm_Access_Action_Type actionType, Elm_Access_Action_Info* actionInfo, int x, int y)
1283 {
1284   bool ret = false;
1285
1286   if( NULL == mAdaptor || NULL == actionInfo )
1287   {
1288     return ret;
1289   }
1290
1291   Dali::AccessibilityManager accessibilityManager = Dali::AccessibilityManager::Get();
1292   if( accessibilityManager )
1293   {
1294     int touchType = actionInfo->mouse_type;
1295     int touchX = x >= 0 ? x : actionInfo->x;
1296     int touchY = y >= 0 ? y : actionInfo->y;
1297
1298     switch(actionType)
1299     {
1300       case ELM_ACCESS_ACTION_HIGHLIGHT:
1301       case ELM_ACCESS_ACTION_READ:
1302       {
1303         ret = accessibilityManager.HandleActionReadEvent((unsigned int)x, (unsigned int)y, true);
1304       }
1305       break;
1306
1307       case ELM_ACCESS_ACTION_OVER:
1308       {
1309         ret = accessibilityManager.HandleActionReadEvent((unsigned int)x, (unsigned int)y, false);
1310       }
1311       break;
1312
1313       case ELM_ACCESS_ACTION_HIGHLIGHT_PREV:
1314       {
1315         // if actionInfo->highlight_end is true, need to handle end_of_list sound feedback
1316         ret = accessibilityManager.HandleActionPreviousEvent(actionInfo->highlight_end);
1317         if(!ret)
1318         {
1319           // when focus moving was failed, clear the focus
1320           accessibilityManager.HandleActionClearFocusEvent();
1321         }
1322       }
1323       break;
1324
1325       case ELM_ACCESS_ACTION_HIGHLIGHT_NEXT:
1326       {
1327         // if actionInfo->highlight_end is true, need to handle end_of_list sound feedback
1328         ret = accessibilityManager.HandleActionNextEvent(actionInfo->highlight_end);
1329         if(!ret)
1330         {
1331           // when focus moving was failed, clear the focus
1332           accessibilityManager.HandleActionClearFocusEvent();
1333         }
1334       }
1335       break;
1336
1337       case ELM_ACCESS_ACTION_ACTIVATE:
1338       {
1339         ret = accessibilityManager.HandleActionActivateEvent();
1340       }
1341       break;
1342
1343       case ELM_ACCESS_ACTION_UNHIGHLIGHT:
1344       {
1345         ret = accessibilityManager.HandleActionClearFocusEvent();
1346       }
1347       break;
1348
1349       case ELM_ACCESS_ACTION_SCROLL:
1350       {
1351         TouchPoint::State state(TouchPoint::Down);
1352
1353         if (touchType == 0)
1354         {
1355           state = TouchPoint::Down; // mouse down
1356         }
1357         else if (touchType == 1)
1358         {
1359           state = TouchPoint::Motion; // mouse move
1360         }
1361         else if (touchType == 2)
1362         {
1363           state = TouchPoint::Up; // mouse up
1364         }
1365         else
1366         {
1367           state = TouchPoint::Interrupted; // error
1368         }
1369
1370         // Send touch event to accessibility manager.
1371         TouchPoint point( 0, state, (float)touchX, (float)touchY );
1372         ret = accessibilityManager.HandleActionScrollEvent(point, GetCurrentMilliSeconds());
1373       }
1374       break;
1375
1376       case ELM_ACCESS_ACTION_UP:
1377       {
1378         ret = accessibilityManager.HandleActionUpEvent();
1379       }
1380       break;
1381
1382       case ELM_ACCESS_ACTION_DOWN:
1383       {
1384         ret = accessibilityManager.HandleActionDownEvent();
1385       }
1386       break;
1387
1388       case ELM_ACCESS_ACTION_MOUSE:
1389       {
1390         // generate normal mouse event
1391         TouchPoint::State state(TouchPoint::Down);
1392
1393         if (touchType == 0)
1394         {
1395           state = TouchPoint::Down; // mouse down
1396         }
1397         else if (touchType == 1)
1398         {
1399           state = TouchPoint::Motion; // mouse move
1400         }
1401         else if (touchType == 2)
1402         {
1403           state = TouchPoint::Up; // mouse up
1404         }
1405         else
1406         {
1407           state = TouchPoint::Interrupted; // error
1408         }
1409
1410         // Send touch event to accessibility manager.
1411         TouchPoint point( 0, state, (float)touchX, (float)touchY );
1412         ret = accessibilityManager.HandleActionTouchEvent(point, GetCurrentMilliSeconds());
1413       }
1414       break;
1415
1416       case ELM_ACCESS_ACTION_BACK:
1417       default:
1418       {
1419         DALI_LOG_WARNING("[%s:%d]\n", __FUNCTION__, __LINE__);
1420       }
1421
1422       break;
1423     }
1424   }
1425   else
1426   {
1427     DALI_LOG_WARNING("[%s:%d]\n", __FUNCTION__, __LINE__);
1428   }
1429
1430   DALI_LOG_INFO(gEvasPluginLogFilter, Debug::General, "[%s:%d] [action : %d] focus manager returns %s\n", __FUNCTION__, __LINE__, (int)(actionType), ret?"TRUE":"FALSE");
1431
1432   return ret;
1433
1434 }
1435
1436 void EvasPlugin::OnEvasObjectFocusedIn()
1437 {
1438   if(mHasFocus)
1439   {
1440     return;
1441   }
1442   mHasFocus = true;
1443
1444   // If the evas object gains focus and we hide the keyboard then show it again.
1445   if( Dali::Adaptor::IsAvailable() )
1446   {
1447     ConnectEcoreEvent();
1448
1449     Dali::ImfManager imfManager( Dali::ImfManager::Get() );
1450     if( imfManager && imfManager.RestoreAfterFocusLost() )
1451     {
1452       imfManager.Activate();
1453     }
1454
1455     // No need to connect callbacks as KeyboardStatusChanged will be called.
1456
1457     // emit focused signal to application
1458     mFocusedSignalV2.Emit( mEvasPlugin );
1459   }
1460 }
1461
1462 void EvasPlugin::OnEvasObjectFocusedOut()
1463 {
1464   if(!mHasFocus)
1465   {
1466     return;
1467   }
1468   mHasFocus = false;
1469
1470   // If the evas object loses focus then hide the keyboard.
1471   if ( Dali::Adaptor::IsAvailable() )
1472   {
1473     Dali::ImfManager imfManager( Dali::ImfManager::Get() );
1474     if( imfManager && imfManager.RestoreAfterFocusLost() )
1475     {
1476       imfManager.Deactivate();
1477     }
1478
1479     // Clipboard don't support that whether clipboard is shown or not. Hide clipboard.
1480     Dali::Clipboard clipboard = Dali::Clipboard::Get();
1481     clipboard.HideClipboard();
1482
1483     DisconnectEcoreEvent();
1484
1485     // emit unfocused signal to application
1486     mUnFocusedSignalV2.Emit( mEvasPlugin );
1487   }
1488 }
1489
1490 void EvasPlugin::OnEcoreEventSelectionCleared( void* data, int type, void* event )
1491 {
1492   Ecore_X_Event_Selection_Clear* selectionClearEvent( (Ecore_X_Event_Selection_Clear*) event );
1493
1494   if( selectionClearEvent->selection == ECORE_X_SELECTION_SECONDARY )
1495   {
1496     // Request to get the content from Ecore.
1497     ecore_x_selection_secondary_request(selectionClearEvent->win, ECORE_X_SELECTION_TARGET_TEXT);
1498   }
1499 }
1500
1501 void EvasPlugin::OnEcoreEventSelectionNotified(void* data, int type, void* event)
1502 {
1503   Ecore_X_Event_Selection_Notify* selectionNotifyEvent( (Ecore_X_Event_Selection_Notify*) event );
1504
1505   if( selectionNotifyEvent->selection == ECORE_X_SELECTION_SECONDARY )
1506   {
1507     // We have got the selected content, inform the clipboard event listener (if we have one).
1508     Dali::ClipboardEventNotifier clipboardEventNotifier = Dali::ClipboardEventNotifier::Get();
1509     Ecore_X_Selection_Data* selectionData( (Ecore_X_Selection_Data*) selectionNotifyEvent->data );
1510
1511     if ( clipboardEventNotifier )
1512     {
1513       std::string content( (char*) selectionData->data, selectionData->length );
1514
1515       if( !content.empty() )
1516       {
1517         clipboardEventNotifier.SetContent( content );
1518         clipboardEventNotifier.EmitContentSelectedSignal();
1519       }
1520     }
1521
1522     // Claim the ownership of the SECONDARY selection.
1523     ecore_x_selection_secondary_set(selectionNotifyEvent->win, "", 1);
1524   }
1525 }
1526
1527 void EvasPlugin::OnEcoreEventClientMessaged(void* data, int type, void* event)
1528 {
1529   Ecore_X_Event_Client_Message* clientMessageEvent( (Ecore_X_Event_Client_Message*)event );
1530
1531   if(clientMessageEvent->message_type == ecore_x_atom_get(CLIPBOARD_ATOM))
1532   {
1533     std::string message(clientMessageEvent->data.b);
1534     if( message == CLIPBOARD_SET_OWNER_MESSAGE)
1535     {
1536       // Claim the ownership of the SECONDARY selection.
1537       ecore_x_selection_secondary_set(clientMessageEvent->win, "", 1);
1538
1539       // Show the clipboard window
1540       Dali::Clipboard clipboard = Dali::Clipboard::Get();
1541       clipboard.ShowClipboard();
1542     }
1543   }
1544 }
1545
1546 void EvasPlugin::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1547 {
1548   mConnectionTracker.SignalConnected( slotObserver, callback );
1549 }
1550
1551 void EvasPlugin::SignalDisconnected( SlotObserver* signal, CallbackBase* callback )
1552 {
1553   mConnectionTracker.SignalDisconnected( signal, callback );
1554 }
1555
1556 std::size_t EvasPlugin::GetConnectionCount() const
1557 {
1558   return mConnectionTracker.GetConnectionCount();
1559 }
1560
1561 } // namespace Adaptor
1562
1563 } // namespace Internal
1564
1565 } // namespace Dali