From 10b932f1d304707bed4926eecab30cdabce70c8f Mon Sep 17 00:00:00 2001 From: Jiyun Yang Date: Wed, 29 May 2019 16:58:08 +0900 Subject: [PATCH] Introduce Evas-plugin 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 --- build/tizen/configure.ac | 1 + build/tizen/dali-extension.pc.in | 2 +- build/tizen/dali-extension/Makefile.am | 64 ++ build/tizen/dali-extension/configure.ac | 30 + dali-extension/dali-extension.h | 23 + .../devel-api/evas-plugin/evas-plugin.cpp | 138 +++ dali-extension/devel-api/evas-plugin/evas-plugin.h | 346 ++++++++ dali-extension/devel-api/evas-plugin/file.list | 5 + .../internal/evas-plugin/evas-event-handler.cpp | 929 +++++++++++++++++++++ .../internal/evas-plugin/evas-event-handler.h | 219 +++++ .../internal/evas-plugin/evas-event-interface.h | 166 ++++ .../internal/evas-plugin/evas-plugin-impl.cpp | 472 +++++++++++ .../internal/evas-plugin/evas-plugin-impl.h | 329 ++++++++ .../internal/evas-plugin/evas-wrapper.cpp | 154 ++++ dali-extension/internal/evas-plugin/evas-wrapper.h | 125 +++ dali-extension/internal/evas-plugin/file.list | 10 + packaging/dali-extension.spec | 9 +- 17 files changed, 3020 insertions(+), 2 deletions(-) create mode 100755 build/tizen/dali-extension/Makefile.am create mode 100755 build/tizen/dali-extension/configure.ac create mode 100644 dali-extension/dali-extension.h create mode 100755 dali-extension/devel-api/evas-plugin/evas-plugin.cpp create mode 100644 dali-extension/devel-api/evas-plugin/evas-plugin.h create mode 100644 dali-extension/devel-api/evas-plugin/file.list create mode 100644 dali-extension/internal/evas-plugin/evas-event-handler.cpp create mode 100644 dali-extension/internal/evas-plugin/evas-event-handler.h create mode 100644 dali-extension/internal/evas-plugin/evas-event-interface.h create mode 100755 dali-extension/internal/evas-plugin/evas-plugin-impl.cpp create mode 100755 dali-extension/internal/evas-plugin/evas-plugin-impl.h create mode 100644 dali-extension/internal/evas-plugin/evas-wrapper.cpp create mode 100644 dali-extension/internal/evas-plugin/evas-wrapper.h create mode 100644 dali-extension/internal/evas-plugin/file.list diff --git a/build/tizen/configure.ac b/build/tizen/configure.ac index 0676946..99b1911 100755 --- a/build/tizen/configure.ac +++ b/build/tizen/configure.ac @@ -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) diff --git a/build/tizen/dali-extension.pc.in b/build/tizen/dali-extension.pc.in index 41fd4ca..08373bf 100644 --- a/build/tizen/dali-extension.pc.in +++ b/build/tizen/dali-extension.pc.in @@ -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 index 0000000..11f781c --- /dev/null +++ b/build/tizen/dali-extension/Makefile.am @@ -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 index 0000000..06b5c12 --- /dev/null +++ b/build/tizen/dali-extension/configure.ac @@ -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 index 0000000..762dd96 --- /dev/null +++ b/dali-extension/dali-extension.h @@ -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 + +#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 index 0000000..30219a5 --- /dev/null +++ b/dali-extension/devel-api/evas-plugin/evas-plugin.cpp @@ -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 + +// CLASS HEADER +#include + +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 index 0000000..707d6b2 --- /dev/null +++ b/dali-extension/devel-api/evas-plugin/evas-plugin.h @@ -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 + +#include +#include + +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 + * #include + * #include + * #include + * #include + * + * 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 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 index 0000000..7796046 --- /dev/null +++ b/dali-extension/devel-api/evas-plugin/file.list @@ -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 index 0000000..514cfd8 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-event-handler.cpp @@ -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 +#include +#include + +// INTERNAL INCLUDES +#include +#include + +// CLASS HEADER +#include + +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 +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::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( 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( data ); + pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp ); +} + +void EvasPluginEventHandler::OnEvasObjectMouseUp( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Evas_Event_Mouse_Up* eventMouseUp = static_cast( 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( data ); + pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp ); +} + +void EvasPluginEventHandler::OnEvasObjectMouseMove( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Evas_Event_Mouse_Move* eventMouseMove = static_cast( 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( data ); + pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp ); +} + +void EvasPluginEventHandler::OnEvasObjectMouseWheel( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Evas_Event_Mouse_Wheel* eventMouseWheel = static_cast( 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( data ); + pEvasPlugin->OnEvasObjectWheelEvent( wheelEvent ); +} + +void EvasPluginEventHandler::OnEvasObjectMultiTouchDown( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Evas_Event_Multi_Down* eventMultiDown = static_cast( 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( data ); + pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp ); +} + +void EvasPluginEventHandler::OnEvasObjectMultiTouchUp( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Evas_Event_Multi_Up* eventMultiUp = static_cast( 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( data ); + pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp ); +} + +void EvasPluginEventHandler::OnEvasObjectMultiTouchMove( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Evas_Event_Multi_Move* eventMultiMove = static_cast( 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( data ); + pEvasPlugin->OnEvasObjectTouchEvent( point, timeStamp ); +} + +void EvasPluginEventHandler::OnEvasObjectKeyDown( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Evas_Event_Key_Down* keyEvent = static_cast( event ); + + // Create KeyEvent + Integration::KeyEvent integKeyEvent; + + integKeyEvent.state = Integration::KeyEvent::Down; + + FillIntegrationKeyEvent( keyEvent, integKeyEvent ); + + // Feed to EvasPlugin + ( static_cast( data ) )->OnEvasObjectKeyEvent( integKeyEvent ); +} + +void EvasPluginEventHandler::OnEvasObjectKeyUp( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Evas_Event_Key_Up* keyEvent = static_cast( event ); + + // Create KeyEvent + Integration::KeyEvent integKeyEvent; + + integKeyEvent.state = Integration::KeyEvent::Up; + + FillIntegrationKeyEvent( keyEvent, integKeyEvent ); + + // Feed to EvasPlugin + ( static_cast( data ) )->OnEvasObjectKeyEvent( integKeyEvent ); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Geometry callbacks +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void EvasPluginEventHandler::OnEvasObjectMove( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Rect geometry; + evas_object_geometry_get( evasObject, &geometry.x, &geometry.y, &geometry.width, &geometry.height ); + + EvasPluginEventInterface* pEvasPlugin = static_cast( data ); + pEvasPlugin->OnEvasObjectMove( geometry ); +} + +void EvasPluginEventHandler::OnEvasObjectResize( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + Rect geometry; + evas_object_geometry_get( evasObject, &geometry.x, &geometry.y, &geometry.width, &geometry.height ); + + EvasPluginEventInterface* pEvasPlugin = static_cast( data ); + pEvasPlugin->OnEvasObjectResize( geometry ); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Focus callbacks +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void EvasPluginEventHandler::OnEvasObjectFocusIn( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + EvasPluginEventHandler* eventHandler = static_cast( data ); + + eventHandler->EnableEcoreWl2Events(); + eventHandler->GetEvasPluginInterface().OnEvasObjectFocusIn(); +} + +void EvasPluginEventHandler::OnEvasObjectFocusOut( void *data, Evas* evas, Evas_Object* evasObject, void* event ) +{ + EvasPluginEventHandler* eventHandler = static_cast( 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( data ); + pEvasPlugin->OnEvasPostRender(); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Elm Access callbacks +///////////////////////////////////////////////////////////////////////////////////////////////////// + +Eina_Bool EvasPluginEventHandler::OnElmAccessActionHighlight( void* data, Evas_Object* evasObject, Elm_Access_Action_Info* actionInfo ) +{ + EvasPluginEventInterface* pEvasPlugin = static_cast( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( event ); + + EvasPluginEventInterface* pEvasPlugin = static_cast( 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 index 0000000..8b12772 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-event-handler.h @@ -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 +#include +#include +#include +#include +#include + +#include +#include + +// 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 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 index 0000000..9a736d1 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-event-interface.h @@ -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 +#include +#include + +namespace Dali +{ + +template +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& geometry ) = 0; + + /** + * @brief Handle evas object geometry + * + * @param geometry is the resize information of evas object + */ + virtual void OnEvasObjectResize( const Rect& 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 index 0000000..8d624fb --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-plugin-impl.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include + +// CLASS HEADER +#include + +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( 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( 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& geometry ) +{ +} + +void EvasPlugin::OnEvasObjectResize( const Rect& 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 index 0000000..e1527d0 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-plugin-impl.h @@ -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 +#include + +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include + +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 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& geometry ) override; + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectResize + */ + void OnEvasObjectResize( const Rect& 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( 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( 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 index 0000000..ef216ce --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-wrapper.cpp @@ -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 +#include + +// CLASS HEADER +#include + + +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 index 0000000..0728602 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-wrapper.h @@ -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 +#include +#include +#include + +#include + +// INTERNAL INCLUDES + +namespace Dali +{ + +typedef Rect 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 index 0000000..d94bbca --- /dev/null +++ b/dali-extension/internal/evas-plugin/file.list @@ -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 diff --git a/packaging/dali-extension.spec b/packaging/dali-extension.spec index caff888..6853a64 100755 --- a/packaging/dali-extension.spec +++ b/packaging/dali-extension.spec @@ -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 -- 2.7.4