Introduce Evas-plugin 40/206940/14
authorJiyun Yang <ji.yang@samsung.com>
Wed, 29 May 2019 07:58:08 +0000 (16:58 +0900)
committerJiyun Yang <ji.yang@samsung.com>
Fri, 30 Aug 2019 06:42:43 +0000 (15:42 +0900)
Evas-plugin is used by EFL applications that wish to use Dali.
It provides a means for initializing the resources required by the Dali::Core.

Change-Id: I2b4428615e42771f94ee1df3c818386e77349c6f
Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
17 files changed:
build/tizen/configure.ac
build/tizen/dali-extension.pc.in
build/tizen/dali-extension/Makefile.am [new file with mode: 0755]
build/tizen/dali-extension/configure.ac [new file with mode: 0755]
dali-extension/dali-extension.h [new file with mode: 0644]
dali-extension/devel-api/evas-plugin/evas-plugin.cpp [new file with mode: 0755]
dali-extension/devel-api/evas-plugin/evas-plugin.h [new file with mode: 0644]
dali-extension/devel-api/evas-plugin/file.list [new file with mode: 0644]
dali-extension/internal/evas-plugin/evas-event-handler.cpp [new file with mode: 0644]
dali-extension/internal/evas-plugin/evas-event-handler.h [new file with mode: 0644]
dali-extension/internal/evas-plugin/evas-event-interface.h [new file with mode: 0644]
dali-extension/internal/evas-plugin/evas-plugin-impl.cpp [new file with mode: 0755]
dali-extension/internal/evas-plugin/evas-plugin-impl.h [new file with mode: 0755]
dali-extension/internal/evas-plugin/evas-wrapper.cpp [new file with mode: 0644]
dali-extension/internal/evas-plugin/evas-wrapper.h [new file with mode: 0644]
dali-extension/internal/evas-plugin/file.list [new file with mode: 0644]
packaging/dali-extension.spec

index 0676946..99b1911 100755 (executable)
@@ -32,6 +32,7 @@ if test "x$with_tizen_55_or_greater" = "xyes"; then
   AC_CONFIG_SUBDIRS(web-engine-chromium)
   AC_CONFIG_SUBDIRS(web-engine-lwe)
 fi
+AC_CONFIG_SUBDIRS(dali-extension)
 
 devincludepath=${includedir}
 AC_SUBST(devincludepath)
index 41fd4ca..08373bf 100644 (file)
@@ -6,6 +6,6 @@ includedir=@devincludepath@
 Name: DALi extension
 Description: The DALi extension Libaray
 Version: @DALI_EXTENSION_VERSION@
-Requires: dali-toolkit
+Requires: dali-adaptor dali-toolkit
 Libs: -L${libdir} -ldali-extension
 Cflags: -I${includedir}/dali-extension
diff --git a/build/tizen/dali-extension/Makefile.am b/build/tizen/dali-extension/Makefile.am
new file mode 100755 (executable)
index 0000000..11f781c
--- /dev/null
@@ -0,0 +1,64 @@
+#
+# Copyright (c) 2019 Samsung Electronics Co., Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Build the Dali extension library
+
+extension_src_dir = ../../../dali-extension
+
+# evas-plugin
+include ../../../dali-extension/devel-api/evas-plugin/file.list
+include ../../../dali-extension/internal/evas-plugin/file.list
+
+lib_LTLIBRARIES =
+
+lib_LTLIBRARIES += libdali-extension.la
+
+# Todo Evas plugin separation
+libdali_extension_la_SOURCES = \
+            $(evas_plugin_devel_src_files) \
+            $(evas_plugin_internal_src_files)
+
+libdali_extension_la_DEPENDENCIES =
+
+libdali_extension_la_CXXFLAGS = \
+            $(DLOG_CFLAGS) \
+            $(DALI_CFLAGS) \
+            $(DALI_EXTENSION_CFLAGS) \
+            $(DALI_ADAPTOR_INTEGRATION_CFLAGS) \
+            $(ELEMENTARY_CFLAGS) \
+            $(EVAS_CFLAGS) \
+            $(WAYLAND_CFLAGS) \
+            -DEFL_BETA_API_SUPPORT \
+            -I../../../ \
+            -Werror -Wall
+
+libdali_extension_la_LIBADD = \
+            $(DLOG_LIBS) \
+            $(DALI_LIBS) \
+            $(DALI_ADAPTOR_INTEGRATION_LIBS) \
+            $(ELEMENTARY_LIBS) \
+            $(EVAS_LIBS) \
+            $(WAYLAND_LIBS)
+
+libdali_extension_la_LDFLAGS = \
+            -rdynamic
+
+#install headers
+dali_extensiondir = $(devincludepath)/dali-extension
+dali_extension_HEADERS = ../../../dali-extension/dali-extension.h
+
+dali_extension_evasplugindir = $(devincludepath)/dali-extension/devel-api/evas-plugin
+dali_extension_evasplugin_HEADERS = $(evas_plugin_devel_header_files)
diff --git a/build/tizen/dali-extension/configure.ac b/build/tizen/dali-extension/configure.ac
new file mode 100755 (executable)
index 0000000..06b5c12
--- /dev/null
@@ -0,0 +1,30 @@
+4_define([dali_version],[0.1.0])
+AC_INIT([dali], [dali_version])
+AM_INIT_AUTOMAKE([-Wall foreign])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+LT_INIT
+
+DALI_EXTENSION_VERSION=dali_version
+AC_SUBST(DALI_EXTENSION_VERSION)
+
+# For evas-plugin
+PKG_CHECK_MODULES(DALI_ADAPTOR_INTEGRATION, dali-adaptor-integration)
+PKG_CHECK_MODULES(ELEMENTARY, elementary)
+PKG_CHECK_MODULES(EVAS, evas)
+PKG_CHECK_MODULES(WAYLAND, [ecore-wl2])
+
+devincludepath=${includedir}
+AC_SUBST(devincludepath)
+
+AC_CONFIG_FILES([
+Makefile
+])
+
+AC_OUTPUT
diff --git a/dali-extension/dali-extension.h b/dali-extension/dali-extension.h
new file mode 100644 (file)
index 0000000..762dd96
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __DALI_EXTENSION_H__
+#define __DALI_EXTENSION_H__
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-extension/devel-api/evas-plugin/evas-plugin.h>
+
+#endif // __DALI_EXTENSION_H__
diff --git a/dali-extension/devel-api/evas-plugin/evas-plugin.cpp b/dali-extension/devel-api/evas-plugin/evas-plugin.cpp
new file mode 100755 (executable)
index 0000000..30219a5
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-extension/internal/evas-plugin/evas-plugin-impl.h>
+
+// CLASS HEADER
+#include <dali-extension/devel-api/evas-plugin/evas-plugin.h>
+
+namespace Dali
+{
+
+namespace Extension
+{
+
+EvasPlugin EvasPlugin::New( Evas_Object* parentEvasObject, int width, int height, bool isTranslucent )
+{
+  IntrusivePtr< Internal::EvasPlugin > impl = Internal::EvasPlugin::New( parentEvasObject, width, height, isTranslucent );
+
+  // When Initialize(), EvasPlugin creates Adaptor which needs BaseHandle of Internal::EvasPlugin.
+  // In that process, EvasPlugin can be deleted when destroying BaseHandle
+  // so it is needed to count reference before calling Initialize()
+  EvasPlugin evasPlugin = EvasPlugin( impl.Get() );
+
+  impl->Initialize();
+
+  return evasPlugin;
+}
+
+EvasPlugin::EvasPlugin()
+{
+}
+
+EvasPlugin::EvasPlugin( const EvasPlugin& evasPlugin )
+: SceneHolder( evasPlugin )
+{
+}
+
+EvasPlugin& EvasPlugin::operator=( const EvasPlugin& evasPlugin )
+{
+  if( *this != evasPlugin )
+  {
+    BaseHandle::operator=( evasPlugin );
+  }
+  return *this;
+}
+
+EvasPlugin::~EvasPlugin()
+{
+}
+
+void EvasPlugin::Run()
+{
+  Internal::GetImplementation( *this ).Run();
+}
+
+void EvasPlugin::Pause()
+{
+  Internal::GetImplementation( *this ).Pause();
+}
+
+void EvasPlugin::Resume()
+{
+  Internal::GetImplementation( *this ).Resume();
+}
+
+void EvasPlugin::Stop()
+{
+  Internal::GetImplementation( *this ).Stop();
+}
+
+Evas_Object* EvasPlugin::GetAccessEvasObject()
+{
+  return Internal::GetImplementation( *this ).GetAccessEvasObject();
+}
+
+Evas_Object* EvasPlugin::GetDaliEvasObject()
+{
+  return Internal::GetImplementation( *this ).GetDaliEvasObject();
+}
+
+EvasPlugin::EvasPluginSignalType& EvasPlugin::InitSignal()
+{
+  return Internal::GetImplementation( *this ).InitSignal();
+}
+
+EvasPlugin::EvasPluginSignalType& EvasPlugin::TerminateSignal()
+{
+  return Internal::GetImplementation( *this ).TerminateSignal();
+}
+
+EvasPlugin::EvasPluginSignalType& EvasPlugin::PauseSignal()
+{
+  return Internal::GetImplementation( *this ).PauseSignal();
+}
+
+EvasPlugin::EvasPluginSignalType& EvasPlugin::ResumeSignal()
+{
+  return Internal::GetImplementation( *this ).ResumeSignal();
+}
+
+EvasPlugin::EvasPluginSignalType& EvasPlugin::ResizeSignal()
+{
+  return Internal::GetImplementation( *this ).ResizeSignal();
+}
+
+EvasPlugin::EvasPluginSignalType& EvasPlugin::FocusedSignal()
+{
+  return Internal::GetImplementation( *this ).FocusedSignal();
+}
+
+EvasPlugin::EvasPluginSignalType& EvasPlugin::UnFocusedSignal()
+{
+  return Internal::GetImplementation( *this ).UnFocusedSignal();
+}
+
+EvasPlugin::EvasPlugin( Internal::EvasPlugin* evasPlugin )
+: SceneHolder( evasPlugin )
+{
+}
+
+}  // namespace Extension
+
+}  // namespace Dali
diff --git a/dali-extension/devel-api/evas-plugin/evas-plugin.h b/dali-extension/devel-api/evas-plugin/evas-plugin.h
new file mode 100644 (file)
index 0000000..707d6b2
--- /dev/null
@@ -0,0 +1,346 @@
+#ifndef __DALI_EXTENSION_EVAS_PLUGIN_H__
+#define __DALI_EXTENSION_EVAS_PLUGIN_H__
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @addtogroup CAPI_DALI_EXTENSION_FRAMEWORK_MODULE
+ * @{
+ */
+
+// EXTERNAL INCLUDES
+#include <Evas.h>
+
+#include <dali/public-api/signals/dali-signal.h>
+#include <dali/integration-api/adaptors/scene-holder.h>
+
+namespace Dali
+{
+
+namespace Extension
+{
+
+namespace Internal
+{
+class EvasPlugin;
+}
+
+/**
+ * @brief Application class used by EFL applications that wish to use Dali
+ *
+ * An EvasPlugin class object should be created by EFL applications
+ * that wish to use Dali. It provides a mean for initializing the
+ * resources required by the Dali::Core.
+ *
+ * The EvasPlugin class emits several signals which the user can
+ * connect to.  The user should not create any Dali objects in the main
+ * function and instead should connect to the Init signal of the
+ * EvasPlugin and create the Dali objects in the connected callback.
+ *
+ * Tizen EFL applications should follow the example below:
+ *
+ * @code
+ *
+ * #include <app.h>
+ * #include <Elementary.h>
+ * #include <dali/dali.h>
+ * #include <dali-toolkit/dali-toolkit.h>
+ * #include <dali-extension/dali-extension.h>
+ *
+ * using namespace Dali;
+ * using namespace Dali::Toolkit;
+ * using namespace Dali::Extension;
+ *
+ * namespace
+ * {
+ * const char* const APPLICATION_TITLE = "EvasPluginExample";
+ * const int EVAS_PLUGIN_WIDTH = 360;
+ * const int EVAS_PLUGIN_HEIGHT = 360;
+ * }
+ *
+ * class EvasPluginExample : public ConnectionTracker
+ * {
+ * public:
+ *   EvasPluginExample(EvasPlugin evasPlugin)
+ *   : mEvasPlugin(evasPlugin)
+ *   {
+ *     mEvasPlugin.InitSignal().Connect(this, &EvasPluginExample::OnInitialize);
+ *     mEvasPlugin.Run();
+ *   }
+ *
+ *   ~EvasPluginExample()
+ *   {
+ *     mEvasPlugin.Stop();
+ *   }
+ *
+ *   void OnInitialize()
+ *   {
+ *     Stage stage = Stage::GetCurrent();
+ *     stage.SetBackgroundColor( Color::WHITE );
+ *
+ *     TextLabel textLabel = TextLabel::New( "Hello World" );
+ *     textLabel.SetParentOrigin( ParentOrigin::CENTER );
+ *     textLabel.SetAnchorPoint( AnchorPoint::CENTER );
+ *     textLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER );
+ *     textLabel.SetProperty( TextLabel::Property::POINT_SIZE, 40 );
+ *     textLabel.SetName( "helloWorldLabel" );
+ *     stage.Add( textLabel );
+ *
+ *     Animation anim = Animation::New( 3.f );
+ *     anim.SetLooping( true );
+ *     anim.AnimateBy( Property(textLabel, Actor::Property::ORIENTATION), Quaternion(Degree(0.f), Degree(360.f), Degree(0.f)) );
+ *     anim.Play();
+ *   }
+ *
+ * private:
+ *   EvasPlugin mEvasPlugin;
+ * };
+ *
+ * struct app_data
+ * {
+ *   Evas_Object* elm_win;
+ *   EvasPluginExample* evasPluginExample;
+ * };
+ *
+ * static void win_del(void *data, Evas_Object * obj, void *event_info)
+ * {
+ * }
+ *
+ * static bool app_create(void *data)
+ * {
+ *   struct app_data* ad = (struct app_data*)data;
+ *
+ *   // Sets the GL backend for rendering
+ *   elm_config_accel_preference_set("3d");
+ *
+ *   // Creates the elm window
+ *   ad->elm_win = elm_win_add(NULL, APPLICATION_TITLE, ELM_WIN_BASIC);
+ *
+ *   DALI_ASSERT_ALWAYS(ad->elm_win != NULL && "Fail to create elm window.");
+ *
+ *   elm_win_title_set(ad->elm_win, APPLICATION_TITLE);
+ *   elm_win_rotation_with_resize_set(ad->elm_win, 0);
+ *   evas_object_smart_callback_add(ad->elm_win, "delete,request", win_del, ad->elm_win);
+ *   evas_object_show(ad->elm_win);
+ *
+ *   // Adds the background
+ *   Evas_Object* bg = elm_bg_add(ad->elm_win);
+ *   elm_bg_color_set(bg, 255, 255, 255);
+ *   evas_object_size_hint_weight_set(bg, 0,0);
+ *   elm_win_resize_object_add(ad->elm_win, bg);
+ *   evas_object_show(bg);
+ *
+ *   // Creates an Evas plugin
+ *   EvasPlugin evasPlugin = EvasPlugin::New(ad->elm_win, EVAS_PLUGIN_WIDTH, EVAS_PLUGIN_HEIGHT, true);
+ *
+ *   // Creates a Dali application
+ *   ad->evasPluginExample = new EvasPluginExample(evasPlugin);
+ *
+ *   return true;
+ * }
+ *
+ * static void app_terminate(void *data)
+ * {
+ *   struct app_data* ad = (struct app_data*)data;
+ *
+ *   delete ad->evasPluginExample;
+ *   ad->evasPluginExample = NULL;
+ * }
+ *
+ * static void app_pause(void *data)
+ * {
+ * }
+ *
+ * static void app_resume(void *data)
+ * {
+ * }
+ *
+ * static void app_control(app_control_h service, void *data)
+ * {
+ * }
+ *
+ * int main(int argc, char *argv[])
+ * {
+ *   // Initializes the Tizen application framework
+ *   ui_app_lifecycle_callback_s event_callback;
+ *
+ *   event_callback.create = app_create;
+ *   event_callback.terminate = app_terminate;
+ *   event_callback.pause = app_pause;
+ *   event_callback.resume = app_resume;
+ *   event_callback.app_control = app_control;
+ *
+ *   struct app_data ad;
+ *   memset(&ad, 0x0, sizeof(ad));
+ *
+ *   // Runs the Tizen application framework
+ *   return ui_app_main(argc, argv, &event_callback, &ad);
+ * }
+ *
+ * @endcode
+ */
+class DALI_IMPORT_API EvasPlugin : public Dali::Integration::SceneHolder
+{
+public:
+
+  typedef Signal<void (void)> EvasPluginSignalType;
+
+public:
+
+  /**
+   * @brief This is the constructor for Tizen EFL applications
+   *
+   * @param[in] parentEvasObject Parent of the new Evas object
+   * @param[in] width The initial width of the Dali view port
+   * @param[in] height The initial height of the Dali view port
+   * @param[in] isTranslucent Whether the Evas object is translucent or not
+   */
+  static EvasPlugin New( Evas_Object* parentEvasObject, int width, int height, bool isTranslucent );
+
+  /**
+   * @brief Constructs an empty handle
+   */
+  EvasPlugin();
+
+  /**
+   * @brief Copy constructor
+   */
+  EvasPlugin( const EvasPlugin& evasPlugin );
+
+  /**
+   * @brief Assignment operator
+   */
+  EvasPlugin& operator=( const EvasPlugin& evasPlugin );
+
+  /**
+   * @brief Destructor
+   */
+  ~EvasPlugin();
+
+public:
+
+  /**
+   * @brief Runs the Evas plugin (rendering, event handling, etc)
+   */
+  void Run();
+
+  /**
+   * @brief Pauses the Evas plugin
+   */
+  void Pause();
+
+  /**
+   * @brief Resumes the Evas plugin
+   */
+  void Resume();
+
+  /**
+   * @brief Stops the Evas plugin
+   */
+  void Stop();
+
+  /**
+   * @brief This returns the Evas_Object* which is created internally
+   *
+   * Applications should append this access object to custom focus chain for accessibility
+   *
+   * e.g., elm_object_focus_custom_chain_append(layout, dali_access_object, NULL);
+   *
+   * @return Evas_Object* Elm access object which Dali image Evas object is registered
+   */
+  Evas_Object* GetAccessEvasObject();
+
+  /**
+   * @brief This returns the Evas_Object* which is created internally
+   *
+   * @return Evas_Object* Evas object which is rendered by Dali
+   */
+  Evas_Object* GetDaliEvasObject();
+
+public:  // Signals
+
+  /**
+   * @brief Signal to notify the client when the application is ready to be initialized
+   *
+   * @return The signal
+   */
+  EvasPluginSignalType& InitSignal();
+
+  /**
+   * @brief Signal to notify the user when the application is about to be terminated
+   *
+   * @return The signal
+   */
+  EvasPluginSignalType& TerminateSignal();
+
+  /**
+   * @brief Signal to notify the client when the EvasPlugin is about to be paused
+   *
+   * The user should connect to this signal if the user needs to perform any special
+   * activities when the application is about to be paused.
+   * @return The signal
+   */
+  EvasPluginSignalType& PauseSignal();
+
+  /**
+   * @brief Signal to notify the client when the adpator has resumed
+   *
+   * The user should connect to this signal if the user needs to perform any special
+   * activities when the application has resumed.
+   * @return The signal
+   */
+  EvasPluginSignalType& ResumeSignal();
+
+  /**
+   * @brief Signal to notify the client when the Evas object is resized
+   *
+   * @return The signal
+   */
+  EvasPluginSignalType& ResizeSignal();
+
+  /**
+   * @brief Signal to notify the client when the Evas object gets the keyboard focus
+   *
+   * @return The signal
+   */
+  EvasPluginSignalType& FocusedSignal();
+
+  /**
+   * @brief Signal to notify the client when the Evas object loses the keyboard focus
+   *
+   * @return The signal
+   */
+  EvasPluginSignalType& UnFocusedSignal();
+
+public: // Not intended for application developers
+  /**
+   * @brief Internal constructor
+   */
+  explicit DALI_INTERNAL EvasPlugin( Internal::EvasPlugin* evasPlugin );
+
+};
+
+/**
+ * @}
+ */
+
+}  // namespace Extension
+
+}  // namespace Dali
+
+#endif // __DALI_EXTENSION_EVAS_PLUGIN_H__
diff --git a/dali-extension/devel-api/evas-plugin/file.list b/dali-extension/devel-api/evas-plugin/file.list
new file mode 100644 (file)
index 0000000..7796046
--- /dev/null
@@ -0,0 +1,5 @@
+evas_plugin_devel_header_files = \
+   $(extension_src_dir)/devel-api/evas-plugin/evas-plugin.h
+
+evas_plugin_devel_src_files = \
+   $(extension_src_dir)/devel-api/evas-plugin/evas-plugin.cpp
diff --git a/dali-extension/internal/evas-plugin/evas-event-handler.cpp b/dali-extension/internal/evas-plugin/evas-event-handler.cpp
new file mode 100644 (file)
index 0000000..514cfd8
--- /dev/null
@@ -0,0 +1,929 @@
+/*
+ * Copyright ( c ) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 ( the "License" );
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/devel-api/adaptor-framework/key-devel.h>
+#include <dali/public-api/events/device.h>
+
+// INTERNAL INCLUDES
+#include <dali-extension/internal/evas-plugin/evas-event-interface.h>
+#include <dali-extension/internal/evas-plugin/evas-wrapper.h>
+
+// CLASS HEADER
+#include <dali-extension/internal/evas-plugin/evas-event-handler.h>
+
+namespace Dali
+{
+
+namespace Extension
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+const int TOUCH_DEVICE_ID = 0;
+
+const char* EVAS_OBJECT_FOCUSED_EVENT_NAME = "focused";
+const char* EVAS_OBJECT_UNFOCUSED_EVENT_NAME = "unfocused";
+
+/**
+ * Copied from x server
+ * @brief Retrieve the current milliseconds.
+ *
+ * @return the current milliseconds.
+ */
+unsigned int GetCurrentMilliSeconds( void )
+{
+  struct timeval tv;
+
+  struct timespec tp;
+  static clockid_t clockid;
+
+  if( !clockid )
+  {
+#ifdef CLOCK_MONOTONIC_COARSE
+    if( clock_getres( CLOCK_MONOTONIC_COARSE, &tp ) == 0 && ( tp.tv_nsec / 1000 ) <= 1000 && clock_gettime( CLOCK_MONOTONIC_COARSE, &tp ) == 0 )
+    {
+      clockid = CLOCK_MONOTONIC_COARSE;
+    }
+    else
+#endif
+    if( clock_gettime( CLOCK_MONOTONIC, &tp ) == 0 )
+    {
+      clockid = CLOCK_MONOTONIC;
+    }
+    else
+    {
+      clockid = ~0L;
+    }
+  }
+  if( clockid != ~0L && clock_gettime( clockid, &tp ) == 0 )
+  {
+    return ( tp.tv_sec * 1000 ) + ( tp.tv_nsec / 1000000L );
+  }
+
+  gettimeofday( &tv, NULL );
+  return ( tv.tv_sec * 1000 ) + ( tv.tv_usec / 1000 );
+}
+
+/**
+ * @brief Retrieve the dali screen touch point.
+ *
+ * @param[in] canvasX is the x of canvas position
+ * @param[in] canvasY is the y of canvas position
+ * @param[in] evasObject is rendered by dali
+ * @param[out] screenX is the x of local position of evasObject
+ * @param[out] screenY is the y of local position of evasObject
+ */
+void GetScreenPosition( Evas_Coord canvasX, Evas_Coord canvasY, Evas_Object* evasObject, Evas_Coord &screenX, Evas_Coord &screenY )
+{
+  Evas_Coord objX = 0, objY = 0, objW = 0, objH = 0;
+  evas_object_geometry_get( evasObject, &objX, &objY, &objW, &objH );
+
+  screenX = canvasX - objX;
+  screenY = canvasY - objY;
+}
+
+void ConvertActionInfo( Elm_Access_Action_Info* elmActionInfo, Dali::Extension::Internal::AccessActionInfo&  daliActionInfo )
+{
+  daliActionInfo.x = elmActionInfo->x;
+  daliActionInfo.y = elmActionInfo->y;
+  daliActionInfo.mouseType = elmActionInfo->mouse_type;
+
+  switch( elmActionInfo->action_type )
+  {
+    case ELM_ACCESS_ACTION_HIGHLIGHT:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_HIGHLIGHT;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_READ:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_READ;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_HIGHLIGHT_PREV:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_HIGHLIGHT_PREV;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_HIGHLIGHT_NEXT:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_HIGHLIGHT_NEXT;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_ACTIVATE:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_ACTIVATE;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_UNHIGHLIGHT:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_UNHIGHLIGHT;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_SCROLL:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_SCROLL;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_UP:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_UP;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_DOWN:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_DOWN;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_BACK:
+    {
+      daliActionInfo.actionType = ACCESS_ACTION_BACK;
+    }
+    break;
+
+    default:
+
+    break;
+  }
+
+  switch( elmActionInfo->action_by )
+  {
+    case ELM_ACCESS_ACTION_HIGHLIGHT:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_HIGHLIGHT;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_READ:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_READ;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_HIGHLIGHT_PREV:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_HIGHLIGHT_PREV;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_HIGHLIGHT_NEXT:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_HIGHLIGHT_NEXT;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_ACTIVATE:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_ACTIVATE;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_UNHIGHLIGHT:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_UNHIGHLIGHT;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_SCROLL:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_SCROLL;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_UP:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_UP;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_DOWN:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_DOWN;
+    }
+    break;
+
+    case ELM_ACCESS_ACTION_BACK:
+    {
+      daliActionInfo.actionBy = ACCESS_ACTION_BACK;
+    }
+    break;
+
+    default:
+
+    break;
+  }
+
+  daliActionInfo.highlightCycle = elmActionInfo->highlight_cycle;
+  daliActionInfo.timeStamp = GetCurrentMilliSeconds();
+}
+
+template<typename Type>
+void FillIntegrationKeyEvent( Type keyEvent, Integration::KeyEvent& result )
+{
+  // KeyName
+  if( keyEvent->keyname )
+  {
+    result.keyName = keyEvent->keyname;
+  }
+
+  // LogicalKey
+  if( keyEvent->key )
+  {
+    result.logicalKey = keyEvent->key;
+  }
+
+  // KeyString
+  if( keyEvent->string )
+  {
+    result.keyString = keyEvent->string;
+  }
+
+  // KeyCode
+  if( !strncmp( keyEvent->keyname, "Keycode-", 8 ) )
+  {
+    result.keyCode = atoi( keyEvent->keyname + 8 );
+  }
+  else
+  {
+    int keycode = Dali::DevelKey::GetDaliKeyCode( keyEvent->keyname );
+    result.keyCode = ( keycode == Dali::DALI_KEY_INVALID ) ? 0 : keycode;
+  }
+
+  // Modifier
+  result.keyModifier = 0;
+  if( evas_key_modifier_is_set( keyEvent->modifiers, "Shift" ) )
+  {
+    result.keyModifier |= ECORE_EVENT_MODIFIER_SHIFT;
+  }
+  if( evas_key_modifier_is_set( keyEvent->modifiers, "Alt" ) )
+  {
+    result.keyModifier |= ECORE_EVENT_MODIFIER_ALT;
+  }
+  if( evas_key_modifier_is_set( keyEvent->modifiers, "AltGr" ) )
+  {
+    result.keyModifier |= ECORE_EVENT_MODIFIER_ALTGR;
+  }
+  if( evas_key_modifier_is_set( keyEvent->modifiers, "Control" ) )
+  {
+    result.keyModifier |= ECORE_EVENT_MODIFIER_CTRL;
+  }
+  if( evas_key_modifier_is_set( keyEvent->modifiers, "Win" ) ||
+      evas_key_modifier_is_set( keyEvent->modifiers, "Super" ) ||
+      evas_key_modifier_is_set( keyEvent->modifiers, "Hyper" ) )
+  {
+    result.keyModifier |= ECORE_EVENT_MODIFIER_WIN;
+  }
+
+  // Time
+  result.time = keyEvent->timestamp;
+
+  // Compose
+  if( keyEvent->compose )
+  {
+    result.compose = keyEvent->compose;
+  }
+
+  // DeviceName
+  const char* ecoreDeviceName = ecore_device_name_get( keyEvent->dev );
+  if( ecoreDeviceName )
+  {
+    result.deviceName = ecoreDeviceName;
+  }
+
+  // DeviceClass
+  Ecore_Device_Class ecoreDeviceClass = ecore_device_class_get( keyEvent->dev );
+  switch( ecoreDeviceClass )
+  {
+    case ECORE_DEVICE_CLASS_SEAT:
+    {
+      result.deviceClass = Device::Class::USER;
+      break;
+    }
+    case ECORE_DEVICE_CLASS_KEYBOARD:
+    {
+      result.deviceClass = Device::Class::KEYBOARD;
+      break;
+    }
+    case ECORE_DEVICE_CLASS_MOUSE:
+    {
+      result.deviceClass = Device::Class::MOUSE;
+      break;
+    }
+    case ECORE_DEVICE_CLASS_TOUCH:
+    {
+      result.deviceClass = Device::Class::TOUCH;
+      break;
+    }
+    case ECORE_DEVICE_CLASS_PEN:
+    {
+      result.deviceClass = Device::Class::PEN;
+      break;
+    }
+    case ECORE_DEVICE_CLASS_POINTER:
+    {
+      result.deviceClass = Device::Class::POINTER;
+      break;
+    }
+    case ECORE_DEVICE_CLASS_GAMEPAD:
+    {
+      result.deviceClass = Device::Class::GAMEPAD;
+      break;
+    }
+    default:
+    {
+      result.deviceClass = Device::Class::NONE;
+      break;
+    }
+  }
+
+  // DeviceSubClass
+  Ecore_Device_Subclass ecoreDeviceSubclass = ecore_device_subclass_get( keyEvent->dev );
+
+  switch( ecoreDeviceSubclass )
+  {
+    case ECORE_DEVICE_SUBCLASS_FINGER:
+    {
+      result.deviceSubclass = Device::Subclass::FINGER;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_FINGERNAIL:
+    {
+      result.deviceSubclass = Device::Subclass::FINGERNAIL;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_KNUCKLE:
+    {
+      result.deviceSubclass = Device::Subclass::KNUCKLE;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_PALM:
+    {
+      result.deviceSubclass = Device::Subclass::PALM;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_HAND_SIZE:
+    {
+      result.deviceSubclass = Device::Subclass::HAND_SIDE;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_HAND_FLAT:
+    {
+      result.deviceSubclass = Device::Subclass::HAND_FLAT;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_PEN_TIP:
+    {
+      result.deviceSubclass = Device::Subclass::PEN_TIP;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_TRACKPAD:
+    {
+      result.deviceSubclass = Device::Subclass::TRACKPAD;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_TRACKPOINT:
+    {
+      result.deviceSubclass = Device::Subclass::TRACKPOINT;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_TRACKBALL:
+    {
+      result.deviceSubclass = Device::Subclass::TRACKBALL;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_REMOCON:
+    {
+      result.deviceSubclass = Device::Subclass::REMOCON;
+      break;
+    }
+    case ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD:
+    {
+      result.deviceSubclass = Device::Subclass::VIRTUAL_KEYBOARD;
+      break;
+    }
+    default:
+    {
+      result.deviceSubclass = Device::Subclass::NONE;
+      break;
+    }
+  }
+}
+
+} // anonymous namespace
+
+EvasPluginEventHandler::EvasPluginEventHandler( EvasPluginEventInterface& evasPluginEventInterface )
+: mEvasPluginEventInterface( evasPluginEventInterface )
+{
+  EvasWrapper* evasWrapper = mEvasPluginEventInterface.GetEvasWrapper();
+  Evas_Object* renderTarget = evasWrapper->GetRenderTarget();
+  Evas_Object* accessibilityTarget = evasWrapper->GetAccessibilityTarget();
+  Evas_Object* focusTarget = evasWrapper->GetFocusTarget();
+  Evas* renderTargetAsEvas = evas_object_evas_get( renderTarget );
+
+  // Register the evas event callbacks
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_MOUSE_DOWN,  OnEvasObjectMouseDown,      &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_MOUSE_UP,    OnEvasObjectMouseUp,        &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_MOUSE_MOVE,  OnEvasObjectMouseMove,      &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_MOUSE_WHEEL, OnEvasObjectMouseWheel,     &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_MULTI_DOWN,  OnEvasObjectMultiTouchDown, &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_MULTI_UP,    OnEvasObjectMultiTouchUp,   &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_MULTI_MOVE,  OnEvasObjectMultiTouchMove, &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_KEY_DOWN,    OnEvasObjectKeyDown,        &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_KEY_UP,      OnEvasObjectKeyUp,          &evasPluginEventInterface );
+
+  // Register the evas geometry callbacks
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_MOVE,   OnEvasObjectMove,   &evasPluginEventInterface );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_RESIZE, OnEvasObjectResize, &evasPluginEventInterface );
+
+  // Register the evas focus callbacks
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_FOCUS_IN,  OnEvasObjectFocusIn,  this );
+  evas_object_event_callback_add( renderTarget, EVAS_CALLBACK_FOCUS_OUT, OnEvasObjectFocusOut, this );
+
+  evas_event_callback_add( renderTargetAsEvas, EVAS_CALLBACK_CANVAS_FOCUS_IN,  OnEvasFocusIn,  &evasPluginEventInterface );
+  evas_event_callback_add( renderTargetAsEvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, OnEvasFocusOut, &evasPluginEventInterface );
+
+  // Register the evas render callbacks
+  evas_event_callback_add( renderTargetAsEvas, EVAS_CALLBACK_RENDER_POST, OnEvasRenderPost, &evasPluginEventInterface );
+
+  // Register the elm access action callbacks and these callbacks are disconnected when mElmAccessEvasObject is unregistred
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_HIGHLIGHT,      OnElmAccessActionHighlight,      &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_UNHIGHLIGHT,    OnElmAccessActionUnhighlight,    &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, OnElmAccessActionHighlightNext,  &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_HIGHLIGHT_PREV, OnElmAccessActionHighlightPrev,  &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_ACTIVATE,       OnElmAccessActionActivate,       &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_UP,             OnElmAccessActionUp,             &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_DOWN,           OnElmAccessActionDown,           &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_SCROLL,         OnElmAccessActionScroll,         &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_BACK,           OnElmAccessActionBack,           &evasPluginEventInterface );
+  elm_access_action_cb_set( accessibilityTarget, ELM_ACCESS_ACTION_READ,           OnElmAccessActionRead,           &evasPluginEventInterface );
+
+  // Register the elm focus callbacks
+  evas_object_smart_callback_add( focusTarget, EVAS_OBJECT_FOCUSED_EVENT_NAME,   OnEvasObjectSmartFocused,   this );
+  evas_object_smart_callback_add( focusTarget, EVAS_OBJECT_UNFOCUSED_EVENT_NAME, OnEvasObjectSmartUnfocused, this );
+}
+
+EvasPluginEventHandler::~EvasPluginEventHandler()
+{
+  EvasWrapper* evasWrapper = mEvasPluginEventInterface.GetEvasWrapper();
+  Evas_Object* renderTarget = evasWrapper->GetRenderTarget();
+  Evas_Object* focusTarget = evasWrapper->GetFocusTarget();
+  Evas* renderTargetAsEvas = evas_object_evas_get( renderTarget );
+
+  // Unregister the evas event callbacks.
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_MOUSE_DOWN,  OnEvasObjectMouseDown );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_MOUSE_UP,    OnEvasObjectMouseUp );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_MOUSE_MOVE,  OnEvasObjectMouseMove );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_MOUSE_WHEEL, OnEvasObjectMouseWheel );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_MULTI_DOWN,  OnEvasObjectMultiTouchDown );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_MULTI_UP,    OnEvasObjectMultiTouchUp );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_MULTI_MOVE,  OnEvasObjectMultiTouchMove );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_KEY_DOWN,    OnEvasObjectKeyDown );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_KEY_UP,      OnEvasObjectKeyUp );
+
+  // Unregister the evas geometry callbacks.
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_MOVE,   OnEvasObjectMove );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_RESIZE, OnEvasObjectResize );
+
+  // Unregister the evas focus callbacks
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_FOCUS_IN,  OnEvasObjectFocusIn );
+  evas_object_event_callback_del( renderTarget, EVAS_CALLBACK_FOCUS_OUT, OnEvasObjectFocusOut );
+
+  evas_event_callback_del( renderTargetAsEvas, EVAS_CALLBACK_CANVAS_FOCUS_IN,  OnEvasFocusIn );
+  evas_event_callback_del( renderTargetAsEvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, OnEvasFocusOut );
+
+  // Register the evas render callbacks
+  evas_event_callback_del( renderTargetAsEvas, EVAS_CALLBACK_RENDER_POST, OnEvasRenderPost );
+
+  // Unregister the elm focus callbacks
+  evas_object_smart_callback_del( focusTarget, EVAS_OBJECT_FOCUSED_EVENT_NAME,   OnEvasObjectSmartFocused );
+  evas_object_smart_callback_del( focusTarget, EVAS_OBJECT_UNFOCUSED_EVENT_NAME, OnEvasObjectSmartUnfocused );
+}
+
+void EvasPluginEventHandler::EnableEcoreWl2Events()
+{
+  if( !mEcoreEventHandlers.size() )
+  {
+    // Register Window visibility change events
+    mEcoreEventHandlers.push_back( ecore_event_handler_add( ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, OnEcoreWl2EventWindowVisibilityChange, &mEvasPluginEventInterface ) );
+  }
+}
+
+void EvasPluginEventHandler::DisableEcoreWl2Events()
+{
+  if( mEcoreEventHandlers.size() )
+  {
+    // Unregister Window events
+    for( std::vector<Ecore_Event_Handler*>::iterator iter = mEcoreEventHandlers.begin(), endIter = mEcoreEventHandlers.end(); iter != endIter; ++iter )
+    {
+      ecore_event_handler_del( *iter );
+    }
+    mEcoreEventHandlers.clear();
+  }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// Event callbacks
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void EvasPluginEventHandler::OnEvasObjectMouseDown( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Mouse_Down* eventMouseDown = static_cast<Evas_Event_Mouse_Down*>( event );
+
+  Evas_Coord screenX = 0.0f, screenY = 0.0f;
+  GetScreenPosition( eventMouseDown->canvas.x, eventMouseDown->canvas.y, evasObject, screenX, screenY );
+
+  Dali::Integration::Point point( TouchPoint( TOUCH_DEVICE_ID, TouchPoint::Down, screenX, screenY ) );
+  unsigned long timeStamp = eventMouseDown->timestamp;
+  if( timeStamp < 1 )
+  {
+    timeStamp = GetCurrentMilliSeconds();
+  }
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp );
+}
+
+void EvasPluginEventHandler::OnEvasObjectMouseUp( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Mouse_Up* eventMouseUp = static_cast<Evas_Event_Mouse_Up*>( event );
+
+  Evas_Coord screenX = 0.0f, screenY = 0.0f;
+  GetScreenPosition( eventMouseUp->canvas.x, eventMouseUp->canvas.y, evasObject, screenX, screenY );
+
+  Dali::Integration::Point point( TouchPoint( TOUCH_DEVICE_ID, TouchPoint::Up, screenX, screenY ) );
+  unsigned long timeStamp = eventMouseUp->timestamp;
+  if( timeStamp < 1 )
+  {
+    timeStamp = GetCurrentMilliSeconds();
+  }
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp );
+}
+
+void EvasPluginEventHandler::OnEvasObjectMouseMove( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Mouse_Move* eventMouseMove = static_cast<Evas_Event_Mouse_Move*>( event );
+
+  Evas_Coord screenX = 0.0f, screenY = 0.0f;
+  GetScreenPosition( eventMouseMove->cur.canvas.x, eventMouseMove->cur.canvas.y, evasObject, screenX, screenY );
+
+  Dali::Integration::Point point( TouchPoint( TOUCH_DEVICE_ID, TouchPoint::Motion, screenX, screenY ) );
+  unsigned long timeStamp = eventMouseMove->timestamp;
+  if( timeStamp < 1 )
+  {
+    timeStamp = GetCurrentMilliSeconds();
+  }
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp );
+}
+
+void EvasPluginEventHandler::OnEvasObjectMouseWheel( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Mouse_Wheel* eventMouseWheel = static_cast<Evas_Event_Mouse_Wheel*>( event );
+
+  Evas_Coord screenX = 0.0f, screenY = 0.0f;
+  GetScreenPosition( eventMouseWheel->canvas.x, eventMouseWheel->canvas.y, evasObject, screenX, screenY );
+
+  int direction = eventMouseWheel->direction;
+  unsigned int modifiers = -1;  // TODO: Need to check evas modifier
+  Vector2 point = Vector2( screenX, screenY );
+  int z = eventMouseWheel->z;
+  unsigned int timeStamp = eventMouseWheel->timestamp;
+  if( timeStamp < 1 )
+  {
+    timeStamp = GetCurrentMilliSeconds();
+  }
+
+  Dali::Integration::WheelEvent wheelEvent( Dali::Integration::WheelEvent::MOUSE_WHEEL, direction, modifiers, point, z, timeStamp );
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectWheelEvent( wheelEvent );
+}
+
+void EvasPluginEventHandler::OnEvasObjectMultiTouchDown( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Multi_Down* eventMultiDown = static_cast<Evas_Event_Multi_Down*>( event );
+
+  Evas_Coord screenX = 0.0f, screenY = 0.0f;
+  GetScreenPosition( eventMultiDown->canvas.x, eventMultiDown->canvas.y, evasObject, screenX, screenY );
+
+  Dali::Integration::Point point( TouchPoint( eventMultiDown->device, TouchPoint::Down, screenX, screenY ) );
+  unsigned long timeStamp = eventMultiDown->timestamp;
+  if( timeStamp < 1 )
+  {
+    timeStamp = GetCurrentMilliSeconds();
+  }
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp );
+}
+
+void EvasPluginEventHandler::OnEvasObjectMultiTouchUp( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Multi_Up* eventMultiUp = static_cast<Evas_Event_Multi_Up*>( event );
+
+  Evas_Coord screenX = 0.0f, screenY = 0.0f;
+  GetScreenPosition( eventMultiUp->canvas.x, eventMultiUp->canvas.y, evasObject, screenX, screenY );
+
+  Dali::Integration::Point point( TouchPoint( eventMultiUp->device, TouchPoint::Up, screenX, screenY ) );
+  unsigned long timeStamp = eventMultiUp->timestamp;
+  if( timeStamp < 1 )
+  {
+    timeStamp = GetCurrentMilliSeconds();
+  }
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp );
+}
+
+void EvasPluginEventHandler::OnEvasObjectMultiTouchMove( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Multi_Move* eventMultiMove = static_cast<Evas_Event_Multi_Move*>( event );
+
+  Evas_Coord screenX = 0.0f, screenY = 0.0f;
+  GetScreenPosition( eventMultiMove->cur.canvas.x, eventMultiMove->cur.canvas.y, evasObject, screenX, screenY );
+
+  Dali::Integration::Point point( TouchPoint( eventMultiMove->device, TouchPoint::Motion, screenX, screenY ) );
+  unsigned long timeStamp = eventMultiMove->timestamp;
+  if( timeStamp < 1 )
+  {
+    timeStamp = GetCurrentMilliSeconds();
+  }
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp );
+}
+
+void EvasPluginEventHandler::OnEvasObjectKeyDown( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Key_Down* keyEvent = static_cast<Evas_Event_Key_Down*>( event );
+
+  // Create KeyEvent
+  Integration::KeyEvent integKeyEvent;
+
+  integKeyEvent.state = Integration::KeyEvent::Down;
+
+  FillIntegrationKeyEvent( keyEvent, integKeyEvent );
+
+  // Feed to EvasPlugin
+  ( static_cast<EvasPluginEventInterface*>( data ) )->OnEvasObjectKeyEvent( integKeyEvent );
+}
+
+void EvasPluginEventHandler::OnEvasObjectKeyUp( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Evas_Event_Key_Up* keyEvent = static_cast<Evas_Event_Key_Up*>( event );
+
+  // Create KeyEvent
+  Integration::KeyEvent integKeyEvent;
+
+  integKeyEvent.state = Integration::KeyEvent::Up;
+
+  FillIntegrationKeyEvent( keyEvent, integKeyEvent );
+
+  // Feed to EvasPlugin
+  ( static_cast<EvasPluginEventInterface*>( data ) )->OnEvasObjectKeyEvent( integKeyEvent );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// Geometry callbacks
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void EvasPluginEventHandler::OnEvasObjectMove( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Rect<int> geometry;
+  evas_object_geometry_get( evasObject, &geometry.x, &geometry.y, &geometry.width, &geometry.height );
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectMove( geometry );
+}
+
+void EvasPluginEventHandler::OnEvasObjectResize( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  Rect<int> geometry;
+  evas_object_geometry_get( evasObject, &geometry.x, &geometry.y, &geometry.width, &geometry.height );
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasObjectResize( geometry );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// Focus callbacks
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void EvasPluginEventHandler::OnEvasObjectFocusIn( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  EvasPluginEventHandler* eventHandler = static_cast<EvasPluginEventHandler*>( data );
+
+  eventHandler->EnableEcoreWl2Events();
+  eventHandler->GetEvasPluginInterface().OnEvasObjectFocusIn();
+}
+
+void EvasPluginEventHandler::OnEvasObjectFocusOut( void *data, Evas* evas, Evas_Object* evasObject, void* event )
+{
+  EvasPluginEventHandler* eventHandler = static_cast<EvasPluginEventHandler*>( data );
+
+  eventHandler->DisableEcoreWl2Events();
+  eventHandler->GetEvasPluginInterface().OnEvasObjectFocusOut();
+}
+
+void EvasPluginEventHandler::OnEvasFocusIn( void *data, Evas* evas, void* event )
+{
+}
+
+void EvasPluginEventHandler::OnEvasFocusOut( void *data, Evas* evas, void* event )
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// Render callbacks
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void EvasPluginEventHandler::OnEvasRenderPost( void *data, Evas* evas, void* event )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  pEvasPlugin->OnEvasPostRender();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// Elm Access callbacks
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionHighlight( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionUnhighlight( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionHighlightNext( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionHighlightPrev( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionActivate( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionScroll( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionUp( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionDown( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionBack( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+Eina_Bool EvasPluginEventHandler::OnElmAccessActionRead( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo )
+{
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+  Dali::Extension::Internal::AccessActionInfo daliActionInfo;
+  ConvertActionInfo( actionInfo, daliActionInfo );
+
+  return pEvasPlugin->OnElmAccessibilityActionEvent( daliActionInfo );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// Elm Focus callbacks
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void EvasPluginEventHandler::OnEvasObjectSmartFocused( void *data, Evas_Object* evasObject, void* event )
+{
+  EvasPluginEventHandler* eventHandler = static_cast<EvasPluginEventHandler*>( data );
+  EvasPluginEventInterface& evasPlugin = eventHandler->GetEvasPluginInterface();
+
+  if( eventHandler->mEvasPluginEventInterface.GetEvasWrapper()->GetFocusTarget() == evasObject )
+  {
+    Evas_Object* topWidget = elm_object_top_widget_get( evasObject );
+
+    if( !strcmp( "elm_win", elm_object_widget_type_get( topWidget ) ) )
+    {
+      if( elm_win_focus_highlight_enabled_get( topWidget ) == EINA_TRUE )
+      {
+        // To allow that KeyboardFocusManager can handle the keyboard focus
+        Dali::Integration::KeyEvent fakeKeyEvent( Dali::KeyEvent( "", "", 0, 0, 100, KeyEvent::Down ) );
+
+        evasPlugin.OnEvasObjectKeyEvent( fakeKeyEvent );
+      }
+    }
+
+    evas_object_focus_set( eventHandler->mEvasPluginEventInterface.GetEvasWrapper()->GetRenderTarget(), EINA_TRUE );
+  }
+}
+
+void EvasPluginEventHandler::OnEvasObjectSmartUnfocused( void *data, Evas_Object* evasObject, void* event )
+{
+  EvasPluginEventHandler* eventHandler = static_cast<EvasPluginEventHandler*>( data );
+  if( eventHandler->mEvasPluginEventInterface.GetEvasWrapper()->GetFocusTarget() == evasObject )
+  {
+    evas_object_focus_set( eventHandler->mEvasPluginEventInterface.GetEvasWrapper()->GetRenderTarget(), EINA_FALSE );
+  }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// Ecore Wl2 callbacks
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Eina_Bool EvasPluginEventHandler::OnEcoreWl2EventWindowVisibilityChange( void* data, int type, void* event )
+{
+  Ecore_Wl2_Event_Window_Visibility_Change* eventWindowVisibilityChange = static_cast<Ecore_Wl2_Event_Window_Visibility_Change*>( event );
+
+  EvasPluginEventInterface* pEvasPlugin = static_cast<EvasPluginEventInterface*>( data );
+
+  // 0 is visible and 1 is invisible
+  pEvasPlugin->OnEcoreWl2VisibilityChange( !eventWindowVisibilityChange->fully_obscured );
+
+  return ECORE_CALLBACK_PASS_ON;
+}
+
+}  // namespace Internal
+
+}  // namespace Extension
+
+}  // namespace Dali
diff --git a/dali-extension/internal/evas-plugin/evas-event-handler.h b/dali-extension/internal/evas-plugin/evas-event-handler.h
new file mode 100644 (file)
index 0000000..8b12772
--- /dev/null
@@ -0,0 +1,219 @@
+#ifndef __DALI_EXTENSION_INTERNAL_EVAS_EVENT_HANDLER__
+#define __DALI_EXTENSION_INTERNAL_EVAS_EVENT_HANDLER__
+
+/*
+ * Copyright ( c ) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 ( the "License" );
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <Evas.h>
+#include <Elementary.h>
+#include <Ecore_Wl2.h>
+#include <Ecore_Input.h>
+#include <Ecore_IMF.h>
+#include <Ecore_IMF_Evas.h>
+
+#include <string>
+#include <vector>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+namespace Extension
+{
+
+namespace Internal
+{
+
+class EvasPluginEventInterface;
+
+class EvasPluginEventHandler
+{
+public:
+  /**
+   * @brief Constructor
+   *
+   * @param[in] evasPluginEventInterface Used to send event to evas plugin
+   */
+  EvasPluginEventHandler( EvasPluginEventInterface& evasPluginEventInterface );
+
+  /**
+   * Destructor.
+   */
+  ~EvasPluginEventHandler();
+
+public:
+
+  EvasPluginEventInterface& GetEvasPluginInterface()
+  {
+    return mEvasPluginEventInterface;
+  }
+
+private:
+
+  void EnableEcoreWl2Events();
+
+  void DisableEcoreWl2Events();
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Event callbacks
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Called when the mouse down is received
+   */
+  static void OnEvasObjectMouseDown( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when the mouse up is received
+   */
+  static void OnEvasObjectMouseUp( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when the mouse move is received
+   */
+  static void OnEvasObjectMouseMove( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when the mouse wheel is received
+   */
+  static void OnEvasObjectMouseWheel( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when the multi-touch down is received
+   */
+  static void OnEvasObjectMultiTouchDown( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when the multi-touch up is received
+   */
+  static void OnEvasObjectMultiTouchUp( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when the multi-touch move is received
+   */
+  static void OnEvasObjectMultiTouchMove( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when key down is received
+   */
+  static void OnEvasObjectKeyDown( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when key up is received
+   */
+  static void OnEvasObjectKeyUp( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Geometry callbacks
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Called when move is received
+   */
+  static void OnEvasObjectMove( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when resize is received
+   */
+  static void OnEvasObjectResize( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Focus callbacks
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Called when evas object focus in is received
+   */
+  static void OnEvasObjectFocusIn( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when evas object focus out is received
+   */
+  static void OnEvasObjectFocusOut( void *data, Evas* evas, Evas_Object* evasObject, void* event );
+
+  /**
+   * @brief Called when evas focus in is received
+   */
+  static void OnEvasFocusIn( void *data, Evas* evas, void* event );
+
+  /**
+   * @brief Called when evas focus out is received
+   */
+  static void OnEvasFocusOut( void *data, Evas* evas, void* event );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Render callbacks
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Called when evas render post
+   */
+  static void OnEvasRenderPost( void *data, Evas* evas, void* event );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Elm Access callbacks
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static Eina_Bool OnElmAccessActionHighlight( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionUnhighlight( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionHighlightNext( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionHighlightPrev( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionActivate( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionScroll( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionUp( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionDown( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionBack( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  static Eina_Bool OnElmAccessActionRead( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* info );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Elm Focus callbacks
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void OnEvasObjectSmartFocused( void* data, Evas_Object* evasObject, void* event );
+
+  static void OnEvasObjectSmartUnfocused( void* data, Evas_Object* evasObject, void* event );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Ecore Wl2 callbacks
+  /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static Eina_Bool OnEcoreWl2EventWindowVisibilityChange( void* data, int type, void* event );
+
+private:
+
+  EvasPluginEventInterface&         mEvasPluginEventInterface;
+  std::vector<Ecore_Event_Handler*> mEcoreEventHandlers;
+};
+
+}  // namespace Internal
+
+}  // namespace Extension
+
+}  // namespace Dali
+
+#endif
diff --git a/dali-extension/internal/evas-plugin/evas-event-interface.h b/dali-extension/internal/evas-plugin/evas-event-interface.h
new file mode 100644 (file)
index 0000000..9a736d1
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef __DALI_EXTENSION_INTERNAL_EVAS_EVENT_INTERFACE_H__
+#define __DALI_EXTENSION_INTERNAL_EVAS_EVENT_INTERFACE_H__
+
+/*
+ * Copyright ( c ) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 ( the "License" );
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/events/point.h>
+#include <dali/integration-api/events/wheel-event-integ.h>
+#include <dali/integration-api/events/key-event-integ.h>
+
+namespace Dali
+{
+
+template <typename T>
+class Rect;
+
+struct TouchPoint;
+struct WheelEvent;
+struct KeyEvent;
+
+namespace Extension
+{
+
+namespace Internal
+{
+
+class EvasWrapper;
+
+enum AccessActionType
+{
+   ACCESS_ACTION_FIRST = -1,
+
+   ACCESS_ACTION_HIGHLIGHT,      /* highlight an object */
+
+   ACCESS_ACTION_UNHIGHLIGHT,    /* unhighlight an object */
+
+   ACCESS_ACTION_HIGHLIGHT_NEXT, /* set highlight to next object */
+
+   ACCESS_ACTION_HIGHLIGHT_PREV, /* set highlight to previous object */
+
+   ACCESS_ACTION_ACTIVATE,       /* activate a highlight object */
+
+   ACCESS_ACTION_SCROLL,         /* scroll if one of highlight object parents is scrollable */
+
+   ACCESS_ACTION_UP,             /* change value up of highlight object */
+
+   ACCESS_ACTION_DOWN,           /* change value down of highlight object */
+
+   ACCESS_ACTION_BACK,           /* go back to a previous view (ex: pop naviframe item) */
+
+   ACCESS_ACTION_READ,           /* highlight an object */
+
+   ACCESS_ACTION_LAST
+};
+
+struct AccessActionInfo
+{
+   int              x;
+   int              y;
+   unsigned int     mouseType; /* 0: mouse down
+                                  1: mouse move
+                                  2: mouse up   */
+   AccessActionType actionType;
+   AccessActionType actionBy;
+   bool             highlightCycle : 1;
+   unsigned int     timeStamp;
+};
+
+class EvasPluginEventInterface
+{
+public:
+   /**
+   * @brief Gets an EvasWrapper instance to connect events
+   *
+   * @return The EvasWrapper instance
+   */
+  virtual EvasWrapper* GetEvasWrapper() const = 0;
+
+  /**
+   * @brief Handle evas object event
+   *
+   * @param[in] touchPoint is the information of touch
+   * @param[in] timeStamp is that touch is occured
+   */
+  virtual void OnEvasObjectTouchEvent( Dali::Integration::Point& touchPoint, unsigned long timeStamp ) = 0;
+
+  /**
+   * @brief Handle evas object event
+   *
+   * @param[in] wheelEvent is the information of wheel
+   */
+  virtual void OnEvasObjectWheelEvent( Dali::Integration::WheelEvent& wheelEvent ) = 0;
+
+  /**
+   * @brief Handle evas object event
+   *
+   * @param[in] keyEvent is the information of key
+   */
+  virtual void OnEvasObjectKeyEvent( Dali::Integration::KeyEvent& keyEvent ) = 0;
+
+  /**
+   * @brief Handle evas object geometry
+   *
+   * @param geometry is the move information of evas object
+   */
+  virtual void OnEvasObjectMove( const Rect<int>& geometry ) = 0;
+
+  /**
+   * @brief Handle evas object geometry
+   *
+   * @param geometry is the resize information of evas object
+   */
+  virtual void OnEvasObjectResize( const Rect<int>& geometry ) = 0;
+
+  /**
+   * @brief Handle evas object focus in
+   */
+  virtual void OnEvasObjectFocusIn() = 0;
+
+  /**
+   * @brief Handle evas object focus out
+   */
+  virtual void OnEvasObjectFocusOut() = 0;
+
+  /**
+   * @brief Handle evas object render post
+   */
+  virtual void OnEvasPostRender() = 0;
+
+   /**
+   * @brief Called when the accessibility action event dispatched from elm_access.
+   * @param[in] accessActionInfo elm accessibility action information structure
+   * @return True if the event was handled
+   */
+  virtual bool OnElmAccessibilityActionEvent( AccessActionInfo& accessActionInfo ) = 0;
+
+  /**
+   * @brief Process the ecore wayland visibility.
+   *
+   * @param[in] visibility True is that ecore wayland window is show up and false is not
+   */
+  virtual void OnEcoreWl2VisibilityChange( bool visibility ) = 0;
+};
+
+}  // namespace Internal
+
+}  // namespace Extension
+
+}  // namespace Dali
+
+#endif
diff --git a/dali-extension/internal/evas-plugin/evas-plugin-impl.cpp b/dali-extension/internal/evas-plugin/evas-plugin-impl.cpp
new file mode 100755 (executable)
index 0000000..8d624fb
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/clipboard.h>
+#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
+#include <dali/devel-api/adaptor-framework/accessibility-adaptor.h>
+#include <dali/integration-api/adaptors/adaptor.h>
+#include <dali/integration-api/adaptors/native-render-surface.h>
+#include <dali/integration-api/adaptors/native-render-surface-factory.h>
+#include <dali/integration-api/adaptors/trigger-event-factory.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/stage.h>
+#include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
+#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
+
+// INTERNAL INCLUDES
+#include <dali-extension/internal/evas-plugin/evas-wrapper.h>
+#include <dali-extension/internal/evas-plugin/evas-event-handler.h>
+
+// CLASS HEADER
+#include <dali-extension/internal/evas-plugin/evas-plugin-impl.h>
+
+namespace Dali
+{
+
+namespace Extension
+{
+
+namespace Internal
+{
+
+// Initialize static members
+
+Adaptor* EvasPlugin::mAdaptor = nullptr;
+
+uint32_t EvasPlugin::mEvasPluginCount = 0;
+
+SingletonService EvasPlugin::mSingletonService = SingletonService();
+
+
+IntrusivePtr< EvasPlugin > EvasPlugin::New( Evas_Object* parentEvasObject, int width, int height, bool isTranslucent )
+{
+  IntrusivePtr< EvasPlugin > evasPlugin = new EvasPlugin( parentEvasObject, width, height, isTranslucent );
+  return evasPlugin;
+}
+
+EvasPlugin::EvasPlugin( Evas_Object* parentEvasObject, int width, int height, bool isTranslucent )
+: mEvasWrapper( new EvasWrapper( parentEvasObject, width, height, isTranslucent ) ),
+  mRenderNotification(),
+  mEvasPluginEventHandler(),
+  mState( READY ),
+  mIsFocus( false ),
+  mIsTranslucent( isTranslucent )
+{
+  DALI_ASSERT_ALWAYS( parentEvasObject && "No parent object for the evas plugin." );
+
+  // Increase plugin count.
+  mEvasPluginCount++;
+
+  // Create surface
+  mSurface = std::unique_ptr< RenderSurfaceInterface >( CreateNativeSurface( PositionSize( 0, 0, width, height ), isTranslucent ) );
+}
+
+void EvasPlugin::Initialize()
+{
+  NativeRenderSurface* surface =  static_cast<NativeRenderSurface*>( mSurface.get() );
+
+  Dali::Integration::SceneHolder sceneHolderHandler = Dali::Extension::EvasPlugin( this );
+
+  if( !mAdaptor )
+  {
+    // Create the singleton service
+    mSingletonService = SingletonService::New();
+
+    // Create an adaptor or add new scene holder to the adaptor
+    mAdaptor = &Adaptor::New( sceneHolderHandler, *surface, Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS );
+  }
+  else
+  {
+    mAdaptor->AddWindow( sceneHolderHandler, "", "", mIsTranslucent );
+  }
+
+  // Connect callback to be notified when the surface is rendered
+  TriggerEventFactory triggerEventFactory;
+
+  mRenderNotification = std::unique_ptr< TriggerEventInterface >( triggerEventFactory.CreateTriggerEvent( MakeCallback( this, &EvasPlugin::OnPostRender ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ) );
+
+  surface->SetRenderNotification( mRenderNotification.get() );
+}
+
+EvasPlugin::~EvasPlugin()
+{
+  mEvasPluginCount--;
+
+  if( !mEvasPluginCount )
+  {
+    delete mAdaptor;
+
+    mSingletonService.UnregisterAll();
+  }
+}
+
+void EvasPlugin::Run()
+{
+  if( READY == mState )
+  {
+    if( !mEvasPluginEventHandler )
+    {
+      mEvasPluginEventHandler = std::unique_ptr< EvasPluginEventHandler >( new EvasPluginEventHandler( *this ) );
+    }
+
+    // Start the adaptor
+    mAdaptor->Start();
+
+    mInitSignal.Emit();
+
+    mAdaptor->NotifySceneCreated();
+
+    mState = RUNNING;
+  }
+}
+
+void EvasPlugin::Pause()
+{
+  if( mState == RUNNING )
+  {
+    mState = SUSPENDED;
+
+    Hide();
+
+    mPauseSignal.Emit();
+  }
+}
+
+void EvasPlugin::Resume()
+{
+  if( mState == SUSPENDED )
+  {
+    Show();
+
+    mResumeSignal.Emit();
+
+    mState = RUNNING;
+  }
+}
+
+void EvasPlugin::Stop()
+{
+  if( mState != STOPPED )
+  {
+    // Stop the adaptor
+    mAdaptor->Stop();
+    mState = STOPPED;
+
+    mTerminateSignal.Emit();
+  }
+}
+
+Dali::Any EvasPlugin::GetNativeHandle() const
+{
+  return mEvasWrapper->GetNativeWindow();
+}
+
+NativeRenderSurface* EvasPlugin::GetNativeRenderSurface() const
+{
+  return dynamic_cast< NativeRenderSurface* >( mSurface.get() );
+}
+
+Evas_Object* EvasPlugin::GetAccessEvasObject()
+{
+  return mEvasWrapper->GetAccessibilityTarget();
+}
+
+Evas_Object* EvasPlugin::GetDaliEvasObject()
+{
+  return mEvasWrapper->GetFocusTarget();
+}
+
+void EvasPlugin::ResizeSurface( int width, int height )
+{
+  if( !mSurface || !mAdaptor || width <= 1 || height <= 1 )
+  {
+    return;
+  }
+
+  PositionSize currentSize = mSurface->GetPositionSize();
+  if( currentSize.width == width && currentSize.height == height )
+  {
+    return;
+  }
+
+  mSurface->MoveResize( PositionSize( 0, 0, width, height ) );
+
+  SurfaceResized();
+
+  Adaptor::SurfaceSize newSize( width, height );
+
+  // When surface size is updated, inform adaptor of resizing and emit ResizeSignal
+  mAdaptor->SurfaceResizePrepare( mSurface.get(), newSize );
+
+  mResizeSignal.Emit();
+
+  mAdaptor->SurfaceResizeComplete( mSurface.get(), newSize );
+}
+
+void EvasPlugin::OnPostRender()
+{
+  // Bind offscreen surface to the evas object
+  NativeRenderSurface* surface = GetNativeRenderSurface();
+
+  DALI_ASSERT_DEBUG( surface && "Surface is null in EvasPlugin" );
+
+  tbm_surface_h tbmSurface = AnyCast<tbm_surface_h>( surface->GetDrawable() );
+
+  if( !tbmSurface )
+  {
+    return;
+  }
+
+  mEvasWrapper->BindTBMSurface( tbmSurface );
+
+  mEvasWrapper->RequestRender();
+
+  surface->ReleaseLock();
+}
+
+EvasWrapper* EvasPlugin::GetEvasWrapper() const
+{
+  return mEvasWrapper.get();
+}
+
+void EvasPlugin::OnEvasObjectTouchEvent( Dali::Integration::Point& touchPoint, unsigned long timeStamp )
+{
+  FeedTouchPoint( touchPoint, timeStamp );
+}
+
+void EvasPlugin::OnEvasObjectWheelEvent( Dali::Integration::WheelEvent& wheelEvent )
+{
+  FeedWheelEvent( wheelEvent );
+}
+
+void EvasPlugin::OnEvasObjectKeyEvent( Dali::Integration::KeyEvent& keyEvent )
+{
+  FeedKeyEvent( keyEvent );
+}
+
+void EvasPlugin::OnEvasObjectMove( const Rect<int>& geometry )
+{
+}
+
+void EvasPlugin::OnEvasObjectResize( const Rect<int>& geometry )
+{
+  ResizeSurface( geometry.width, geometry.height );
+}
+
+void EvasPlugin::OnEvasObjectFocusIn()
+{
+  if( !mIsFocus )
+  {
+    mFocusedSignal.Emit();
+
+    mIsFocus = true;
+  }
+}
+
+void EvasPlugin::OnEvasObjectFocusOut()
+{
+  if( mIsFocus )
+  {
+    mIsFocus = false;
+
+    Toolkit::KeyInputFocusManager focusManager = Toolkit::KeyInputFocusManager::Get();
+    Toolkit::Control currentFocused = focusManager.GetCurrentFocusControl();
+    if( currentFocused )
+    {
+      focusManager.RemoveFocus( currentFocused );
+    }
+
+    Clipboard::Get().HideClipboard();
+
+    mUnFocusedSignal.Emit();
+  }
+}
+
+void EvasPlugin::OnEvasPostRender()
+{
+}
+
+bool EvasPlugin::OnElmAccessibilityActionEvent( AccessActionInfo& accessActionInfo )
+{
+  bool ret = false;
+
+  if( mAdaptor == nullptr )
+  {
+    return ret;
+  }
+
+  Dali::AccessibilityAdaptor accessibilityAdaptor = Dali::AccessibilityAdaptor::Get();
+  if( accessibilityAdaptor )
+  {
+    switch( accessActionInfo.actionBy )
+    {
+      case Dali::Extension::Internal::ACCESS_ACTION_HIGHLIGHT:
+      case Dali::Extension::Internal::ACCESS_ACTION_READ:
+      {
+        ret = accessibilityAdaptor.HandleActionReadEvent( (unsigned int)accessActionInfo.x, (unsigned int)accessActionInfo.y, true );
+      }
+      break;
+
+      case Dali::Extension::Internal::ACCESS_ACTION_HIGHLIGHT_PREV:
+      {
+        // if accessActionInfo.highlight_end is true, need to handle end_of_list sound feedback
+        ret = accessibilityAdaptor.HandleActionPreviousEvent( accessActionInfo.highlightCycle );
+        if(!ret)
+        {
+          // when focus moving was failed, clear the focus
+          accessibilityAdaptor.HandleActionClearFocusEvent();
+        }
+      }
+      break;
+
+      case Dali::Extension::Internal::ACCESS_ACTION_HIGHLIGHT_NEXT:
+      {
+        // if accessActionInfo.highlight_cycle is true, need to handle end_of_list sound feedback
+        ret = accessibilityAdaptor.HandleActionNextEvent( accessActionInfo.highlightCycle );
+        if(!ret)
+        {
+          // when focus moving was failed, clear the focus
+          accessibilityAdaptor.HandleActionClearFocusEvent();
+        }
+      }
+      break;
+
+      case Dali::Extension::Internal::ACCESS_ACTION_ACTIVATE:
+      {
+        ret = accessibilityAdaptor.HandleActionActivateEvent();
+      }
+      break;
+
+      case Dali::Extension::Internal::ACCESS_ACTION_UNHIGHLIGHT:
+      {
+        ret = accessibilityAdaptor.HandleActionClearFocusEvent();
+      }
+      break;
+
+      case Dali::Extension::Internal::ACCESS_ACTION_SCROLL:
+      {
+        Evas_Object* eo = mEvasWrapper->GetAccessibilityTarget();
+
+        if( eo )
+        {
+          int touchType = accessActionInfo.mouseType;
+
+          TouchPoint::State state( TouchPoint::Down );
+
+          if( touchType == 0 )
+          {
+            state = TouchPoint::Down; // mouse down
+          }
+          else if( touchType == 1 )
+          {
+            state = TouchPoint::Motion; // mouse move
+          }
+          else if( touchType == 2 )
+          {
+            state = TouchPoint::Up; // mouse up
+          }
+          else
+          {
+            state = TouchPoint::Interrupted; // error
+          }
+
+          // Send touch event to accessibility manager.
+          Evas_Coord rel_x, rel_y, obj_x,  obj_y, obj_w, obj_h;
+
+          evas_object_geometry_get( eo, &obj_x,  &obj_y, &obj_w, &obj_h );
+
+          rel_x = accessActionInfo.x - obj_x;
+          rel_y = accessActionInfo.y - obj_y;
+
+          TouchPoint point( 0, state, (float)rel_x, (float)rel_y );
+
+          ret = accessibilityAdaptor.HandleActionScrollEvent( point, accessActionInfo.timeStamp );
+        }
+      }
+      break;
+
+      case Dali::Extension::Internal::ACCESS_ACTION_UP:
+      {
+        ret = accessibilityAdaptor.HandleActionUpEvent();
+      }
+      break;
+
+      case Dali::Extension::Internal::ACCESS_ACTION_DOWN:
+      {
+        ret = accessibilityAdaptor.HandleActionDownEvent();
+      }
+      break;
+
+      case Dali::Extension::Internal::ACCESS_ACTION_BACK:
+      default:
+      {
+        DALI_LOG_WARNING( "[%s:%d]\n", __FUNCTION__, __LINE__ );
+      }
+
+      break;
+    }
+  }
+  else
+  {
+    DALI_LOG_WARNING( "[%s:%d]\n", __FUNCTION__, __LINE__ );
+  }
+
+  return ret;
+}
+
+void EvasPlugin::OnEcoreWl2VisibilityChange( bool visibility )
+{
+  DALI_LOG_RELEASE_INFO( "EvasPlugin::OnEcoreWl2VisibilityChange( %s )", visibility ? "T" : "F" );
+
+  if( visibility )
+  {
+    Show();
+  }
+  else
+  {
+    Hide();
+
+    mAdaptor->ReleaseSurfaceLock();
+  }
+}
+
+void EvasPlugin::Show()
+{
+  if( !mVisible )
+  {
+    mVisible = true;
+
+    mAdaptor->OnWindowShown();
+  }
+}
+
+void EvasPlugin::Hide()
+{
+  if( mVisible )
+  {
+    mVisible = false;
+
+    mAdaptor->OnWindowHidden();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Extension
+
+} // namespace Dali
diff --git a/dali-extension/internal/evas-plugin/evas-plugin-impl.h b/dali-extension/internal/evas-plugin/evas-plugin-impl.h
new file mode 100755 (executable)
index 0000000..e1527d0
--- /dev/null
@@ -0,0 +1,329 @@
+#ifndef __DALI_EXTENSION_INTERNAL_EVAS_PLUGIN_H__
+#define __DALI_EXTENSION_INTERNAL_EVAS_PLUGIN_H__
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <memory>
+#include <Ecore_IMF_Evas.h>
+
+#include <dali/devel-api/adaptor-framework/singleton-service.h>
+#include <dali/integration-api/adaptors/scene-holder-impl.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/signals/connection-tracker.h>
+
+// INTERNAL INCLUDES
+#include <dali-extension/internal/evas-plugin/evas-event-interface.h>
+#include <dali-extension/devel-api/evas-plugin/evas-plugin.h>
+
+namespace Dali
+{
+class Adaptor;
+class NativeRenderSurface;
+class TriggerEventInterface;
+
+namespace Extension
+{
+
+namespace Internal
+{
+
+class EvasPluginEventHandler;
+class EvasWrapper;
+
+/**
+ * Implementation of the EvasPlugin class.
+ */
+class EvasPlugin : public Dali::Internal::Adaptor::SceneHolder,
+                   public ConnectionTracker,
+                   public Extension::Internal::EvasPluginEventInterface
+{
+public:
+
+  typedef Dali::Extension::EvasPlugin::EvasPluginSignalType EvasPluginSignalType;
+
+  /**
+   * @brief Create a new evas plugin
+   * @param[in] parentEvasObject A pointer of the parent evas object
+   * @param[in] width The width of Dali view port
+   * @param[in] height The height of Dali view port
+   * @param[in] isTranslucent Whether the evas object is translucent or not
+   */
+  static IntrusivePtr<EvasPlugin> New( Evas_Object* parentEvasObject, int width, int height, bool isTranslucent );
+
+public:
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::Start()
+   */
+  void Run();
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::Pause()
+   */
+  void Pause();
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::Resume()
+   */
+  void Resume();
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::Stop()
+   */
+  void Stop();
+
+  /**
+   * @brief Gets the native handle.
+   * @note When users call this function, it wraps the actual type used by the underlying system.
+   * @return The native handle or an empty handle
+   */
+  Dali::Any GetNativeHandle() const override;
+
+  /**
+   * @brief Get the native render surface
+   * @return The render surface
+   */
+  NativeRenderSurface* GetNativeRenderSurface() const;
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::GetAccessEvasObject()
+   */
+  Evas_Object* GetAccessEvasObject();
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::GetDaliEvasObject()
+   */
+  Evas_Object* GetDaliEvasObject();
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::InitSignal()
+   */
+  EvasPluginSignalType& InitSignal()
+  {
+    return mInitSignal;
+  }
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::TerminateSignal()
+   */
+  EvasPluginSignalType& TerminateSignal()
+  {
+    return mTerminateSignal;
+  }
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::PauseSignal()
+   */
+  EvasPluginSignalType& PauseSignal()
+  {
+   return mPauseSignal;
+  }
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::ResumeSignal()
+   */
+  EvasPluginSignalType& ResumeSignal()
+  {
+    return mResumeSignal;
+  }
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::ResizeSignal()
+   */
+  EvasPluginSignalType& ResizeSignal()
+  {
+    return mResizeSignal;
+  }
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::FocusedSignal()
+   */
+  EvasPluginSignalType& FocusedSignal()
+  {
+    return mFocusedSignal;
+  }
+
+  /**
+   * @copydoc Dali::Extension::EvasPlugin::UnFocusedSignal()
+   */
+  EvasPluginSignalType& UnFocusedSignal()
+  {
+    return mUnFocusedSignal;
+  }
+
+  /*
+   * @bried Initialize EvasPlugin
+   */
+  void Initialize();
+
+private:
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::GetEvasWrapper
+   */
+  EvasWrapper* GetEvasWrapper() const override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectTouchEvent
+   */
+  void OnEvasObjectTouchEvent( Dali::Integration::Point& touchPoint, unsigned long timeStamp ) override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectWheelEvent
+   */
+  void OnEvasObjectWheelEvent( Dali::Integration::WheelEvent& wheelEvent ) override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectKeyEvent
+   */
+  void OnEvasObjectKeyEvent( Dali::Integration::KeyEvent& keyEvent ) override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectMove
+   */
+  void OnEvasObjectMove( const Rect<int>& geometry ) override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectResize
+   */
+  void OnEvasObjectResize( const Rect<int>& geometry ) override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectFocusIn
+   */
+  void OnEvasObjectFocusIn() override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectFocusOut
+   */
+  void OnEvasObjectFocusOut() override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasRenderPost
+   */
+  void OnEvasPostRender() override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessibilityActionEvent
+   */
+  bool OnElmAccessibilityActionEvent( AccessActionInfo& actionInfo ) override;
+
+  /**
+   * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEcoreWl2VisibilityChange
+   */
+  void OnEcoreWl2VisibilityChange( bool visibility ) override;
+
+  /**
+   * @brief Resize the surface
+   * @param[in] width The width value
+   * @param[in] height The height value
+   */
+  void ResizeSurface( int width, int height );
+
+  /**
+   * This function is called after drawing by dali.
+   */
+  void OnPostRender();
+
+  /**
+   * @brief Shows the EvasPlugin if it is hidden.
+   */
+  void Show();
+
+  /**
+   * @brief Hides the EvasPlugin if it is showing.
+   */
+  void Hide();
+
+private:
+  /**
+   * Private constructor
+   * @param[in] parentEvasObject A pointer of the parent evas object
+   * @param[in] width The width of Dali view port
+   * @param[in] height The height of Dali view port
+   * @param[in] isTranslucent Whether the evas object is translucent or not
+   */
+  EvasPlugin( Evas_Object* parentEvasObject, int width, int height, bool isTranslucent );
+
+  /**
+   * Destructor
+   */
+  virtual ~EvasPlugin();
+
+  // Undefined
+  EvasPlugin( const EvasPlugin& );
+  EvasPlugin& operator=( EvasPlugin& );
+
+private:
+
+  enum State
+  {
+    READY,
+    RUNNING,
+    SUSPENDED,
+    STOPPED,
+  };
+
+  static Adaptor*                           mAdaptor;
+  static uint32_t                           mEvasPluginCount;
+  static SingletonService                   mSingletonService;
+
+  std::unique_ptr< EvasWrapper >            mEvasWrapper;
+  std::unique_ptr< TriggerEventInterface >  mRenderNotification;
+  std::unique_ptr< EvasPluginEventHandler > mEvasPluginEventHandler;
+
+  EvasPluginSignalType                      mInitSignal;
+  EvasPluginSignalType                      mTerminateSignal;
+  EvasPluginSignalType                      mPauseSignal;
+  EvasPluginSignalType                      mResumeSignal;
+  EvasPluginSignalType                      mResizeSignal;
+  EvasPluginSignalType                      mFocusedSignal;
+  EvasPluginSignalType                      mUnFocusedSignal;
+
+  State                                     mState;
+  bool                                      mIsFocus;
+  bool                                      mIsTranslucent;
+};
+
+inline EvasPlugin& GetImplementation( Extension::EvasPlugin& evasPlugin )
+{
+  DALI_ASSERT_ALWAYS( evasPlugin && "evasPluing handle is empty" );
+
+  BaseObject& handle = evasPlugin.GetBaseObject();
+
+  return static_cast<EvasPlugin&>( handle );
+}
+
+inline const EvasPlugin& GetImplementation( const Extension::EvasPlugin& evasPlugin )
+{
+  DALI_ASSERT_ALWAYS( evasPlugin && "evasPlugin handle is empty" );
+
+  const BaseObject& handle = evasPlugin.GetBaseObject();
+
+  return static_cast<const EvasPlugin&>( handle );
+}
+
+} // namespace Internal
+
+} // namespace Extension
+
+} // namespace Dali
+
+#endif // __DALI_EXTENSION_INTERNAL_EVAS_PLUGIN_H__
diff --git a/dali-extension/internal/evas-plugin/evas-wrapper.cpp b/dali-extension/internal/evas-plugin/evas-wrapper.cpp
new file mode 100644 (file)
index 0000000..ef216ce
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright ( c ) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 ( the "License" );
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/rect.h>
+#include <Elementary.h>
+
+// CLASS HEADER
+#include <dali-extension/internal/evas-plugin/evas-wrapper.h>
+
+
+namespace Dali
+{
+
+namespace Extension
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+const char* IMAGE_EVAS_OBJECT_NAME = "dali-evas-plugin";
+const char* ELM_OBJECT_STYLE = "transparent";
+const char* ELM_OBJECT_CONTAINER_PART_NAME = "elm.swallow.content";
+
+} // unnamed namespace
+
+EvasWrapper::EvasWrapper( Evas_Object* pluginParent, int width, int height, bool transparent )
+: mEcoreEvas( nullptr ),
+  mImageEvasObject( nullptr ),
+  mAccessibilityEvasObject( nullptr ),
+  mFocusEvasObject( nullptr )
+{
+  Evas* evas = evas_object_evas_get( pluginParent );
+  mEcoreEvas = ecore_evas_ecore_evas_get( evas );
+
+  // Create the image evas object
+  mImageEvasObject = evas_object_image_filled_add( evas );
+  evas_object_name_set( mImageEvasObject, IMAGE_EVAS_OBJECT_NAME );
+  evas_object_image_content_hint_set( mImageEvasObject, EVAS_IMAGE_CONTENT_HINT_DYNAMIC );
+  evas_object_image_alpha_set( mImageEvasObject, transparent ? EINA_TRUE : EINA_FALSE );
+  evas_object_image_size_set( mImageEvasObject, width, height );
+  evas_object_size_hint_weight_set( mImageEvasObject, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND );
+  evas_object_size_hint_align_set( mImageEvasObject, EVAS_HINT_FILL, EVAS_HINT_FILL );
+
+  // Register the elm access to image evas object
+  mAccessibilityEvasObject = elm_access_object_register( mImageEvasObject, pluginParent );
+
+  // Create a button and set style as "focus", if does not want to show the focus, then "transparent"
+  mFocusEvasObject = elm_button_add( pluginParent );
+
+  // Don't need to show the focus boundary here
+  elm_object_style_set( mFocusEvasObject, ELM_OBJECT_STYLE );
+
+  // Set the image evas object to focus object, but event should not be propagated
+  elm_object_part_content_set( mFocusEvasObject, ELM_OBJECT_CONTAINER_PART_NAME, mImageEvasObject );
+  evas_object_propagate_events_set( mImageEvasObject, EINA_FALSE );
+
+  // Set the evas object you want to make focusable as the content of the swallow part
+  evas_object_size_hint_weight_set( mFocusEvasObject, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND );
+  evas_object_size_hint_align_set( mFocusEvasObject, EVAS_HINT_FILL, EVAS_HINT_FILL );
+
+  evas_object_move( mFocusEvasObject, 0, 0 );
+  evas_object_resize( mFocusEvasObject, width, height );
+  evas_object_show( mFocusEvasObject );
+}
+
+EvasWrapper::~EvasWrapper()
+{
+  // Delete the elm focus evas object
+  evas_object_del( mFocusEvasObject );
+  mFocusEvasObject = NULL;
+
+  // Unregister elm_access_object
+  elm_access_object_unregister( mAccessibilityEvasObject );
+  mAccessibilityEvasObject = NULL;
+
+  // Delete the image evas object
+  evas_object_del( mImageEvasObject );
+  mImageEvasObject = NULL;
+}
+
+Ecore_Wl2_Window* EvasWrapper::GetNativeWindow() const
+{
+  return ecore_evas_wayland2_window_get( mEcoreEvas );
+}
+
+PositionSize EvasWrapper::GetGeometry() const
+{
+  PositionSize geometry;
+  evas_object_geometry_get( mImageEvasObject, &geometry.x, &geometry.y, &geometry.width, &geometry.height );
+  return geometry;
+}
+
+Evas_Object* EvasWrapper::GetRenderTarget() const
+{
+  return mImageEvasObject;
+}
+
+Evas_Object* EvasWrapper::GetAccessibilityTarget() const
+{
+  return mAccessibilityEvasObject;
+}
+
+Evas_Object* EvasWrapper::GetFocusTarget() const
+{
+  return mFocusEvasObject;
+}
+
+void EvasWrapper::SetFocus()
+{
+  evas_object_focus_set( mImageEvasObject, EINA_TRUE );
+}
+
+void EvasWrapper::BindTBMSurface( tbm_surface_h surface )
+{
+  Evas_Native_Surface nativeSurface;
+  nativeSurface.type = EVAS_NATIVE_SURFACE_TBM;
+  nativeSurface.version = EVAS_NATIVE_SURFACE_VERSION;
+  nativeSurface.data.tbm.buffer = surface;
+  nativeSurface.data.tbm.rot = 0;
+  nativeSurface.data.tbm.ratio = 0;
+  nativeSurface.data.tbm.flip = 0;
+
+  evas_object_image_native_surface_set( mImageEvasObject, &nativeSurface );
+}
+
+void EvasWrapper::RequestRender()
+{
+  evas_object_image_pixels_dirty_set( mImageEvasObject, EINA_TRUE );
+  ecore_evas_manual_render( mEcoreEvas );
+}
+
+}  // namespace Internal
+
+}  // namespace Extension
+
+}  // namespace Dali
\ No newline at end of file
diff --git a/dali-extension/internal/evas-plugin/evas-wrapper.h b/dali-extension/internal/evas-plugin/evas-wrapper.h
new file mode 100644 (file)
index 0000000..0728602
--- /dev/null
@@ -0,0 +1,125 @@
+#ifndef __DALI_EXTENSION_INTERNAL_EVAS_WRAPPER__
+#define __DALI_EXTENSION_INTERNAL_EVAS_WRAPPER__
+
+/*
+ * Copyright ( c ) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 ( the "License" );
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Ecore_Wl2.h>
+#include <tbm_surface.h>
+
+#include <dali/public-api/math/rect.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+typedef Rect<int> PositionSize;
+
+namespace Extension
+{
+
+namespace Internal
+{
+
+/**
+ * EvasWrapper is a class which holds a parent evas object for the EvasPlugin.
+ * This creates essential evas ebjects (RenderTarget, AccessibiltyTarget, FocusTarget) to connect evas to Dali properly,
+ * and also provides evas rendering interfaces.
+ */
+class EvasWrapper
+{
+
+public:
+
+  /**
+   * @brief Constructor
+   * @param[in] pluginParent An parent evas object of a evas plugin
+   * @param[in] width The initial width of the Dali view port
+   * @param[in] height The initial height of the Dali view port
+   * @param[in] transparent Whether the Evas object is transparent or not
+   */
+  EvasWrapper( Evas_Object* pluginParent, int width, int height, bool transparent );
+
+  /**
+   * @brief Destructor
+   */
+  ~EvasWrapper();
+
+  /**
+   * @brief Gets current native window object
+   * @return The ecore window object
+   */
+  Ecore_Wl2_Window* GetNativeWindow() const;
+
+  /**
+   * @brief Gets the geometry information
+   * @return The geometry information
+   */
+  PositionSize GetGeometry() const;
+
+  /**
+   * @brief Gets the rendering target evas object
+   * @return The rendering target object
+   */
+  Evas_Object* GetRenderTarget() const;
+
+  /**
+   * @brief Gets the accessibility target evas object
+   * @return The accessibility target object
+   */
+  Evas_Object* GetAccessibilityTarget() const;
+
+  /**
+   * @brief Gets the focus target evas object
+   * @return The focus target object
+   */
+  Evas_Object* GetFocusTarget() const;
+
+  /**
+   * @brief Sets focus
+   */
+  void SetFocus();
+
+  /**
+   * @brief Bind a tbm surface
+   */
+  void BindTBMSurface( tbm_surface_h surface );
+
+  /**
+   * @brief Request rendering
+   */
+  void RequestRender();
+
+private:
+
+  Ecore_Evas*  mEcoreEvas;
+  Evas_Object* mImageEvasObject;
+  Evas_Object* mAccessibilityEvasObject;
+  Evas_Object* mFocusEvasObject;
+};
+
+}  // namespace Internal
+
+}  // namespace Extension
+
+}  // namespace Dali
+
+#endif // __DALI_EXTENSION_INTERNAL_EVAS_WRAPPER__
diff --git a/dali-extension/internal/evas-plugin/file.list b/dali-extension/internal/evas-plugin/file.list
new file mode 100644 (file)
index 0000000..d94bbca
--- /dev/null
@@ -0,0 +1,10 @@
+evas_plugin_internal_header_files = \
+   $(extension_src_dir)/internal/evas-plugin/evas-event-handler.h \
+   $(extension_src_dir)/internal/evas-plugin/evas-event-interface.h \
+   $(extension_src_dir)/internal/evas-plugin/evas-plugin-impl.h \
+   $(extension_src_dir)/internal/evas-plugin/evas-wrapper.h
+
+evas_plugin_internal_src_files = \
+   $(extension_src_dir)/internal/evas-plugin/evas-event-handler.cpp \
+   $(extension_src_dir)/internal/evas-plugin/evas-plugin-impl.cpp \
+   $(extension_src_dir)/internal/evas-plugin/evas-wrapper.cpp
index caff888..6853a64 100755 (executable)
@@ -23,6 +23,12 @@ BuildRequires:  pkgconfig(dali-adaptor)
 BuildRequires:  pkgconfig(dali-toolkit)
 BuildRequires:  pkgconfig(dlog)
 
+# For evas-plugin
+BuildRequires:  pkgconfig(dali-adaptor-integration)
+BuildRequires:  pkgconfig(elementary)
+BuildRequires:  pkgconfig(evas)
+BuildRequires:  pkgconfig(ecore-wl2)
+
 %description
 dali-extension
 
@@ -307,11 +313,12 @@ exit 0
 %manifest dali-extension.manifest
 %defattr(-,root,root,-)
 %{_sysconfdir}/profile.d/dali.sh
+%{_libdir}/libdali-extension.so*
 %license LICENSE
 
 %files devel
 %defattr(-,root,root,-)
-%{_includedir}/%{name}/
+%{_includedir}/%{name}/*
 %{_libdir}/pkgconfig/*.pc
 
 %files key-extension