From eabc893d6ced3a46cae1386b6f7d73279566f820 Mon Sep 17 00:00:00 2001 From: Seoyeon Kim Date: Mon, 5 Aug 2019 14:10:58 +0900 Subject: [PATCH] [Tizen] Introduce Evas-plugin This reverts commit 17766d708b8f769ba24a85b3231d6d1f3a18c9c8. Change-Id: I56b17cdc10e4b4a437eb32b1b0879f9ae762aafb --- build/tizen/configure.ac | 1 + build/tizen/dali-extension.pc.in | 2 +- build/tizen/evas-plugin/Makefile.am | 61 ++ build/tizen/evas-plugin/configure.ac | 30 + dali-extension/dali-extension.h | 23 + .../devel-api/evas-plugin/evas-plugin.cpp | 130 ++++ dali-extension/devel-api/evas-plugin/evas-plugin.h | 336 +++++++++ dali-extension/devel-api/evas-plugin/file.list | 5 + .../evas-plugin/ecore-wl-event-handler.cpp | 186 +++++ .../internal/evas-plugin/ecore-wl-event-handler.h | 78 ++ .../internal/evas-plugin/evas-event-handler.cpp | 805 +++++++++++++++++++++ .../internal/evas-plugin/evas-event-handler.h | 230 ++++++ .../evas-plugin/evas-plugin-event-interface.h | 151 ++++ .../internal/evas-plugin/evas-plugin-impl.cpp | 664 +++++++++++++++++ .../internal/evas-plugin/evas-plugin-impl.h | 393 ++++++++++ .../evas-plugin/evas-plugin-visibility-interface.h | 46 ++ dali-extension/internal/evas-plugin/file.list | 11 + packaging/dali-extension.spec | 10 +- 18 files changed, 3160 insertions(+), 2 deletions(-) create mode 100755 build/tizen/evas-plugin/Makefile.am create mode 100755 build/tizen/evas-plugin/configure.ac create mode 100644 dali-extension/dali-extension.h create mode 100755 dali-extension/devel-api/evas-plugin/evas-plugin.cpp create mode 100755 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/ecore-wl-event-handler.cpp create mode 100644 dali-extension/internal/evas-plugin/ecore-wl-event-handler.h 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-plugin-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-plugin-visibility-interface.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..ac23e70 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(evas-plugin) 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/evas-plugin/Makefile.am b/build/tizen/evas-plugin/Makefile.am new file mode 100755 index 0000000..5073ba6 --- /dev/null +++ b/build/tizen/evas-plugin/Makefile.am @@ -0,0 +1,61 @@ +# +# Copyright (c) 2015 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 evas plugin + +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_public_src_files) \ + $(evas_plugin_internal_src_files) + +libdali_extension_la_DEPENDENCIES = + +libdali_extension_la_CXXFLAGS = \ + $(DLOG_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_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_public_header_files) diff --git a/build/tizen/evas-plugin/configure.ac b/build/tizen/evas-plugin/configure.ac new file mode 100755 index 0000000..06b5c12 --- /dev/null +++ b/build/tizen/evas-plugin/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..e0bbc37 --- /dev/null +++ b/dali-extension/devel-api/evas-plugin/evas-plugin.cpp @@ -0,0 +1,130 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include "evas-plugin.h" + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Extension +{ + +EvasPlugin EvasPlugin::New(Evas_Object* parentEvasObject, int width, int height, bool transparent) +{ + Internal::EvasPluginPtr internal = Internal::EvasPlugin::New(parentEvasObject, width, height, transparent); + return EvasPlugin(internal.Get()); +} + +EvasPlugin::EvasPlugin() +{ +} + +EvasPlugin::EvasPlugin(const EvasPlugin& evasPlugin) +: BaseHandle(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::GetDaliAccessEvasObject() +{ + return Internal::GetImplementation(*this).GetDaliAccessEvasObject(); +} + +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) +: BaseHandle(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 100755 index 0000000..fcf7acb --- /dev/null +++ b/dali-extension/devel-api/evas-plugin/evas-plugin.h @@ -0,0 +1,336 @@ +#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 means 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 and EFL applications should follow the example below: + * + * @code + * #include + * #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 = 480; + * const int EVAS_PLUGIN_HEIGHT = 800; + * } + * + * class DaliApplication : public ConnectionTracker + * { + * public: + * DaliApplication(EvasPlugin evasPlugin) + * : mEvasPlugin(evasPlugin) + * { + * mEvasPlugin.InitSignal().Connect(this, &DaliApplication::OnInitialize); + * mEvasPlugin.Run(); + * } + * + * ~DaliApplication() + * { + * mEvasPlugin.Stop(); + * } + * + * void OnInitialize(EvasPlugin& evasPlugin) + * { + * Stage stage = Stage::GetCurrent(); + * + * TextLabel textLabel = TextLabel::New( "Hello World" ); + * textLabel.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + * textLabel.SetName( "helloWorldLabel" ); + * stage.Add( textLabel ); + * } + * + * private: + * EvasPlugin mEvasPlugin; + * }; + * + * struct app_data + * { + * Evas_Object* elm_win; + * DaliApplication* daliApplication; + * }; + * + * 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->daliApplication = new DaliApplication(evasPlugin); + * + * return true; + * } + * + * static void app_terminate(void *data) + * { + * struct app_data* ad = (struct app_data*)data; + * + * delete ad->daliApplication; + * ad->daliApplication = 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 BaseHandle +{ +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] transparent Whether the Evas object is transparent or not + */ + static EvasPlugin New(Evas_Object* parentEvasObject, int width, int height, bool transparent); + + /** + * @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 for accessibility. + * + * 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* GetDaliAccessEvasObject(); + + /** + * @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 adaptor 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..6f1cafe --- /dev/null +++ b/dali-extension/devel-api/evas-plugin/file.list @@ -0,0 +1,5 @@ +evas_plugin_public_header_files = \ + $(extension_src_dir)/devel-api/evas-plugin/evas-plugin.h + +evas_plugin_public_src_files = \ + $(extension_src_dir)/devel-api/evas-plugin/evas-plugin.cpp diff --git a/dali-extension/internal/evas-plugin/ecore-wl-event-handler.cpp b/dali-extension/internal/evas-plugin/ecore-wl-event-handler.cpp new file mode 100644 index 0000000..8f01016 --- /dev/null +++ b/dali-extension/internal/evas-plugin/ecore-wl-event-handler.cpp @@ -0,0 +1,186 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include "ecore-wl-event-handler.h" + +namespace Dali +{ + +namespace Extension +{ + +namespace Internal +{ + +namespace +{ + +const int ECORE_WL_EVENT_COUNT = 4; + +//const char* CLIPBOARD_ATOM = "CBHM_MSG"; +//const char* CLIPBOARD_SET_OWNER_MESSAGE = "SET_OWNER"; + +} + +struct EcoreWlEventHandler::Impl +{ + Impl(EcoreWlEventHandler* eventHandler, Ecore_Wl2_Window* window) + : mEventHandler(eventHandler) + , mWindow(window) + , mEcoreEventHandlers(ECORE_WL_EVENT_COUNT) + { +#if 0 + // Register Client message events - accessibility etc + mEcoreEventHandlers.push_back(ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, EcoreWlEventClientMessage, eventHandler)); + + // Register Selection events - clipboard selection, Drag & Drop selection etc + mEcoreEventHandlers.push_back(ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, EcoreWlEventSelectionClear, eventHandler)); + mEcoreEventHandlers.push_back(ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, EcoreWlEventSelectionNotify, eventHandler)); +#endif + // Register Window visibility change events + mEcoreEventHandlers.push_back(ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, EcoreWlEventWindowVisibilityChange, eventHandler)); + + } + + ~Impl() + { + for(std::vector::iterator iter = mEcoreEventHandlers.begin(), endIter = mEcoreEventHandlers.end(); iter != endIter; ++iter) + { + ecore_event_handler_del(*iter); + } + } + + static Eina_Bool EcoreWlEventClientMessage(void* data, int type, void* event) + { +#if 0 + Ecore_X_Event_Client_Message* eventClientMessage = static_cast(event); + EcoreWlEventHandler* eventHandler = static_cast(data); + + if (eventClientMessage->win == eventHandler->mImpl->mWindow) + { + if (eventClientMessage->message_type == ecore_x_atom_get(CLIPBOARD_ATOM)) + { + if (!strcmp(eventClientMessage->data.b, CLIPBOARD_SET_OWNER_MESSAGE)) + { + // Claim the ownership of the SECONDARY selection + ecore_x_selection_secondary_set(eventClientMessage->win, "", 1); + + // Show the clipboard window + Clipboard::Get().ShowClipboard(); + } + } + } +#endif + + return ECORE_CALLBACK_PASS_ON; + } + + static Eina_Bool EcoreWlEventSelectionClear(void* data, int type, void* event) + { +#if 0 + Ecore_X_Event_Selection_Clear* eventSelectionClear = static_cast(event); + EcoreWlEventHandler* eventHandler = static_cast(data); + + if (eventSelectionClear->win == eventHandler->mImpl->mWindow) + { + if (eventSelectionClear->selection == ECORE_X_SELECTION_SECONDARY) + { + // Request to get the content from Ecore + ecore_x_selection_secondary_request(eventSelectionClear->win, ECORE_X_SELECTION_TARGET_TEXT); + } + } +#endif + + return ECORE_CALLBACK_PASS_ON; + } + + static Eina_Bool EcoreWlEventSelectionNotify(void* data, int type, void* event) + { +#if 0 + Ecore_X_Event_Selection_Notify* eventSelectionNotify = static_cast(event); + EcoreWlEventHandler* eventHandler = static_cast(data); + + if (eventSelectionNotify->win == eventHandler->mImpl->mWindow) + { + Ecore_X_Selection_Data* selectionData = static_cast(eventSelectionNotify->data); + if (selectionData->data) + { + if (eventSelectionNotify->selection == ECORE_X_SELECTION_SECONDARY) + { + std::string content(reinterpret_cast(selectionData->data), selectionData->length); + + ClipboardEventNotifier clipboardEventNotifier = ClipboardEventNotifier::Get(); + clipboardEventNotifier.SetContent(content); + clipboardEventNotifier.EmitContentSelectedSignal(); + + // Claim the ownership of the SECONDARY selection + ecore_x_selection_secondary_set(eventSelectionNotify->win, "", 1); + + DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreWlEventSelectionNotify: Content(%d):\n" , selectionData->length ); + DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" ); + DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data ); + DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" ); + } + } + } +#endif + + return ECORE_CALLBACK_PASS_ON; + } + + static Eina_Bool EcoreWlEventWindowVisibilityChange(void* data, int type, void* event) + { + Ecore_Wl2_Event_Window_Visibility_Change* eventWindowVisibilityChange = static_cast(event); + + EcoreWlEventHandler* eventHandler = static_cast(data); + + // 0 is visible and 1 is invisible + eventHandler->SendEcoreWlVisibility(!eventWindowVisibilityChange->fully_obscured); + + return ECORE_CALLBACK_PASS_ON; + } + + EcoreWlEventHandler* mEventHandler; + Ecore_Wl2_Window* mWindow; + std::vector mEcoreEventHandlers; +}; + +EcoreWlEventHandler::EcoreWlEventHandler(Ecore_Wl2_Window* window, + EvasPluginVisibilityInterface& evasPluginVisibilityInterface) +: mEvasPluginVisibilityInterface(evasPluginVisibilityInterface) +, mImpl(NULL) +{ + mImpl = new Impl(this, window); +} + +EcoreWlEventHandler::~EcoreWlEventHandler() +{ + delete mImpl; + mImpl = NULL; +} + +void EcoreWlEventHandler::SendEcoreWlVisibility(bool visibility) +{ + mEvasPluginVisibilityInterface.OnEcoreWlVisibility(visibility); +} + +} // namespace Internal + +} // namespace Extension + +} // namespace Dali diff --git a/dali-extension/internal/evas-plugin/ecore-wl-event-handler.h b/dali-extension/internal/evas-plugin/ecore-wl-event-handler.h new file mode 100644 index 0000000..0f55c6c --- /dev/null +++ b/dali-extension/internal/evas-plugin/ecore-wl-event-handler.h @@ -0,0 +1,78 @@ +#ifndef __DALI_EXTENSION_INTERNAL_ECORE_X_EVENT_HANDLER__ +#define __DALI_EXTENSION_INTERNAL_ECORE_X_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 + +// INTERNAL INCLUDES +#include "evas-plugin-visibility-interface.h" + +namespace Dali +{ + +namespace Extension +{ + +namespace Internal +{ + +class EvasPluginVisibilityInterface; + +class EcoreWlEventHandler +{ +public: + /** + * @brief Constructor + * + * @param[in] window is id of ecore wayland window. + * @param[in] evasPluginVisibilityInterface Used to send ecore wayland event to evas plugin + */ + EcoreWlEventHandler(Ecore_Wl2_Window* window, EvasPluginVisibilityInterface& evasPluginVisibilityInterface); + + /** + * @brief Destructor + */ + ~EcoreWlEventHandler(); + + /** + * @brief Send the ecore wayland visibility. + * + * @param[in] visibility True is that ecore wayland window is show up and false is not + */ + void SendEcoreWlVisibility(bool visibility); + +private: + EvasPluginVisibilityInterface& mEvasPluginVisibilityInterface; + + struct Impl; + Impl* mImpl; +}; + +} // namespace Internal + +} // namespace Extension + +} // namespace Dali + +#endif 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..f07a5e0 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-event-handler.cpp @@ -0,0 +1,805 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include "evas-event-handler.h" + +namespace Dali +{ + +namespace Extension +{ + +namespace Internal +{ + +/** + * Copied from x server + * @brief Retrieve the current milliseconds. + * + * @return the current milliseconds. + */ +static 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); +} + +namespace +{ + +const int TOUCH_DEVICE_ID = 0; + +const char* EVAS_OBJECT_FOCUSED_EVENT_NAME = "focused"; +const char* EVAS_OBJECT_UNFOCUSED_EVENT_NAME = "unfocused"; + +/** + * @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; +} + +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER +/** + * @brief Evas_Modifier enums in Ecore_Input.h do not match Ecore_Event_Modifier in Ecore_Input.h. + * This function converts from Evas_Modifier to Ecore_Event_Modifier enums. + * + * @param[in] evasModifier the Evas_Modifier input. + * @return the Ecore_Event_Modifier output. + */ +unsigned int EvasModifierToEcoreModifier(Evas_Modifier* evasModifier) +{ + unsigned int modifier = 0; // If no other matches returns NONE. + + if (evas_key_modifier_is_set(evasModifier, "Shift")) + { + modifier |= ECORE_EVENT_MODIFIER_SHIFT; + } + + if (evas_key_modifier_is_set(evasModifier, "Alt")) + { + modifier |= ECORE_EVENT_MODIFIER_ALT; + } + + if (evas_key_modifier_is_set(evasModifier, "AltGr")) + { + modifier |= ECORE_EVENT_MODIFIER_ALTGR; + } + + if (evas_key_modifier_is_set(evasModifier, "Control")) + { + modifier |= ECORE_EVENT_MODIFIER_CTRL; + } + + if (evas_key_modifier_is_set(evasModifier, "Win") || + evas_key_modifier_is_set(evasModifier, "Super") || + evas_key_modifier_is_set(evasModifier, "Hyper")) + { + modifier |= ECORE_EVENT_MODIFIER_WIN; + } + + return modifier; +} +#endif + + +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(); +} + +} // namespace + +EvasEventHandler::EvasEventHandler(Evas_Object* imageEvasObject, + Evas_Object* elmAccessEvasObject, + Evas_Object* elmFocusEvasObject, + EvasPluginEventInterface& evasPluginEventInterface) +: mEvasPluginEventInterface(evasPluginEventInterface) +, mEvas(evas_object_evas_get(imageEvasObject)) +, mImageEvasObject(imageEvasObject) +, mElmAccessEvasObject(elmAccessEvasObject) +, mElmFocusEvasObject(elmFocusEvasObject) +{ + // Register the evas event callbacks + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_MOUSE_DOWN, OnEvasObjectMouseDown, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_MOUSE_UP, OnEvasObjectMouseUp, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_MOUSE_MOVE, OnEvasObjectMouseMove, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_MOUSE_WHEEL, OnEvasObjectMouseWheel, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_MULTI_DOWN, OnEvasObjectMultiTouchDown, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_MULTI_UP, OnEvasObjectMultiTouchUp, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_MULTI_MOVE, OnEvasObjectMultiTouchMove, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_KEY_DOWN, OnEvasObjectKeyDown, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_KEY_UP, OnEvasObjectKeyUp, &evasPluginEventInterface); + + // Register the evas geometry callbacks + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_MOVE, OnEvasObjectMove, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_RESIZE, OnEvasObjectResize, &evasPluginEventInterface); + + // Register the evas focus callbacks + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_FOCUS_IN, OnEvasObjectFocusIn, &evasPluginEventInterface); + evas_object_event_callback_add(mImageEvasObject, EVAS_CALLBACK_FOCUS_OUT, OnEvasObjectFocusOut, &evasPluginEventInterface); + + evas_event_callback_add(mEvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, OnEvasFocusIn, &evasPluginEventInterface); + evas_event_callback_add(mEvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, OnEvasFocusOut, &evasPluginEventInterface); + + // Register the evas render callbacks + evas_event_callback_add(mEvas, 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(mElmAccessEvasObject, ELM_ACCESS_ACTION_HIGHLIGHT, OnElmAccessActionHighlight, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_UNHIGHLIGHT, OnElmAccessActionUnhighlight, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, OnElmAccessActionHighlightNext, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_HIGHLIGHT_PREV, OnElmAccessActionHighlightPrev, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_ACTIVATE, OnElmAccessActionActivate, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_UP, OnElmAccessActionUp, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_DOWN, OnElmAccessActionDown, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_SCROLL, OnElmAccessActionScroll, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_BACK, OnElmAccessActionBack, &evasPluginEventInterface); + elm_access_action_cb_set(mElmAccessEvasObject, ELM_ACCESS_ACTION_READ, OnElmAccessActionRead, &evasPluginEventInterface); + + // Register the elm focus callbacks + evas_object_smart_callback_add(mElmFocusEvasObject, EVAS_OBJECT_FOCUSED_EVENT_NAME, OnEvasObjectSmartFocused, this); + evas_object_smart_callback_add(mElmFocusEvasObject, EVAS_OBJECT_UNFOCUSED_EVENT_NAME, OnEvasObjectSmartUnfocused, this); +} + +EvasEventHandler::~EvasEventHandler() +{ + // Unregister the evas event callbacks. + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_MOUSE_DOWN, OnEvasObjectMouseDown); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_MOUSE_UP, OnEvasObjectMouseUp); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_MOUSE_MOVE, OnEvasObjectMouseMove); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_MOUSE_WHEEL, OnEvasObjectMouseWheel); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_MULTI_DOWN, OnEvasObjectMultiTouchDown); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_MULTI_UP, OnEvasObjectMultiTouchUp); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_MULTI_MOVE, OnEvasObjectMultiTouchMove); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_KEY_DOWN, OnEvasObjectKeyDown); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_KEY_UP, OnEvasObjectKeyUp); + + // Unregister the evas geometry callbacks. + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_MOVE, OnEvasObjectMove); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_RESIZE, OnEvasObjectResize); + + // Unregister the evas focus callbacks + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_FOCUS_IN, OnEvasObjectFocusIn); + evas_object_event_callback_del(mImageEvasObject, EVAS_CALLBACK_FOCUS_OUT, OnEvasObjectFocusOut); + + evas_event_callback_del(mEvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, OnEvasFocusIn); + evas_event_callback_del(mEvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, OnEvasFocusOut); + + // Register the evas render callbacks + evas_event_callback_del(mEvas, EVAS_CALLBACK_RENDER_POST, OnEvasRenderPost); + + // Unregister the elm focus callbacks + evas_object_smart_callback_del(mElmFocusEvasObject, EVAS_OBJECT_FOCUSED_EVENT_NAME, OnEvasObjectSmartFocused); + evas_object_smart_callback_del(mElmFocusEvasObject, EVAS_OBJECT_UNFOCUSED_EVENT_NAME, OnEvasObjectSmartUnfocused); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Event callbacks +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void EvasEventHandler::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); + + TouchPoint touchPoint = 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(touchPoint, timeStamp); +} + +void EvasEventHandler::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); + + TouchPoint touchPoint = 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(touchPoint, timeStamp); +} + +void EvasEventHandler::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); + + TouchPoint touchPoint = 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(touchPoint, timeStamp); +} + +void EvasEventHandler::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(); + } + + WheelEvent wheelEvent(WheelEvent::MOUSE_WHEEL, direction, modifiers, point, z, timeStamp); + + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasObjectWheelEvent(wheelEvent); +} + +void EvasEventHandler::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); + + TouchPoint touchPoint = TouchPoint(eventMultiDown->device, TouchPoint::Down, screenX, screenY); + unsigned long timeStamp = eventMultiDown->timestamp; + if (timeStamp < 1) + { + timeStamp = GetCurrentMilliSeconds(); + } + + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasObjectTouchEvent(touchPoint, timeStamp); +} + +void EvasEventHandler::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); + + TouchPoint touchPoint = TouchPoint(eventMultiUp->device, TouchPoint::Up, screenX, screenY); + unsigned long timeStamp = eventMultiUp->timestamp; + if (timeStamp < 1) + { + timeStamp = GetCurrentMilliSeconds(); + } + + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasObjectTouchEvent(touchPoint, timeStamp); +} + +void EvasEventHandler::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); + + TouchPoint touchPoint = TouchPoint(eventMultiMove->device, TouchPoint::Motion, screenX, screenY); + unsigned long timeStamp = eventMultiMove->timestamp; + if (timeStamp < 1) + { + timeStamp = GetCurrentMilliSeconds(); + } + + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasObjectTouchEvent(touchPoint, timeStamp); +} + +void EvasEventHandler::OnEvasObjectKeyDown(void *data, Evas* evas, Evas_Object* evasObject, void* event) +{ +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER + Evas_Event_Key_Down* eventKeyDown = static_cast(event); + bool eventHandled = false; + + // If a device key then skip ecore_imf_context_filter_event. + if (!KeyLookup::IsDeviceButton(eventKeyDown->keyname)) + { + ImfManager imfManager = ImfManager::Get(); + if(imfManager) + { + Ecore_IMF_Context* imfContext = Dali::Internal::Adaptor::ImfManager::GetImplementation(imfManager).GetContext(); + if (imfContext) + { + // We're consuming key down event so we have to pass to IMF so that it can parse it as well. + Ecore_IMF_Event_Key_Down imfEventKeyDown; + ecore_imf_evas_event_key_down_wrap(eventKeyDown, &imfEventKeyDown); + + eventHandled = ecore_imf_context_filter_event(imfContext, ECORE_IMF_EVENT_KEY_DOWN, reinterpret_cast(&imfEventKeyDown)); + + if (!eventHandled) + { + // Menu, home, back button must skip ecore_imf_context_filter_event. + static const char* escapeKeyName = KeyLookup::GetKeyName(DALI_KEY_ESCAPE); + static const char* returnKeyName = KeyLookup::GetKeyName(static_cast(DALI_EXTENSION_INTERNAL_KEY_RETURN)); + static const char* kpEnterKeyName = KeyLookup::GetKeyName(static_cast(DALI_EXTENSION_INTERNAL_KEY_KP_ENTER)); + if ((escapeKeyName && !strcmp(eventKeyDown->keyname, escapeKeyName)) || + (returnKeyName && !strcmp(eventKeyDown->keyname, returnKeyName)) || + (kpEnterKeyName && !strcmp(eventKeyDown->keyname, kpEnterKeyName))) + { + ecore_imf_context_reset(imfContext); + } + } + } + } + } + + // If the event wasn't handled then we should send a key event. + if (!eventHandled) + { + std::string keyName = eventKeyDown->keyname; + std::string keyString = (eventKeyDown->string != NULL) ? eventKeyDown->string : ""; + int keyCode = KeyLookup::GetDaliKeyCode(eventKeyDown->keyname); + int modifier = EvasModifierToEcoreModifier(eventKeyDown->modifiers); + unsigned long timeStamp = eventKeyDown->timestamp; + if (timeStamp < 1) + { + timeStamp = GetCurrentMilliSeconds(); + } + + KeyEvent keyEvent(keyName, keyString, keyCode, modifier, timeStamp, KeyEvent::Down); + + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasObjectKeyEvent(keyEvent); + } +#endif +} + +void EvasEventHandler::OnEvasObjectKeyUp(void *data, Evas* evas, Evas_Object* evasObject, void* event) +{ +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER + Evas_Event_Key_Up* eventKeyUp = static_cast(event); + bool eventHandled = false; + + // Menu, home, back button must skip ecore_imf_context_filter_event. + static const char* menuKeyName = KeyLookup::GetKeyName(DALI_KEY_MENU); + static const char* homeKeyName = KeyLookup::GetKeyName(DALI_KEY_HOME); + static const char* backKeyName = KeyLookup::GetKeyName(DALI_KEY_BACK); + if ((menuKeyName && !strcmp(eventKeyUp->keyname, menuKeyName)) && + (homeKeyName && !strcmp(eventKeyUp->keyname, homeKeyName)) && + (backKeyName && !strcmp(eventKeyUp->keyname, backKeyName))) + { + ImfManager imfManager = ImfManager::Get(); + if(imfManager) + { + Ecore_IMF_Context* imfContext = Dali::Internal::Adaptor::ImfManager::GetImplementation(imfManager).GetContext(); + + if (imfContext) + { + Ecore_IMF_Event_Key_Up imfEventKeyUp; + ecore_imf_evas_event_key_up_wrap(eventKeyUp, &imfEventKeyUp); + + eventHandled = ecore_imf_context_filter_event(imfContext, ECORE_IMF_EVENT_KEY_UP, reinterpret_cast(&imfEventKeyUp)); + } + } + } + + if (!eventHandled) + { + std::string keyName = eventKeyUp->keyname; + std::string keyString = (eventKeyUp->string != NULL) ? eventKeyUp->string : ""; + int keyCode = KeyLookup::GetDaliKeyCode(eventKeyUp->keyname); + int modifier = EvasModifierToEcoreModifier(eventKeyUp->modifiers); + unsigned long timeStamp = eventKeyUp->timestamp; + if (timeStamp < 1) + { + timeStamp = GetCurrentMilliSeconds(); + } + + KeyEvent keyEvent(keyName, keyString, keyCode, modifier, timeStamp, KeyEvent::Up); + + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasObjectKeyEvent(keyEvent); + } +#endif +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Geometry callbacks +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void EvasEventHandler::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 EvasEventHandler::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 EvasEventHandler::OnEvasObjectFocusIn(void *data, Evas* evas, Evas_Object* evasObject, void* event) +{ + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasObjectFocusIn(); +} + +void EvasEventHandler::OnEvasObjectFocusOut(void *data, Evas* evas, Evas_Object* evasObject, void* event) +{ + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasObjectFocusOut(); +} + +void EvasEventHandler::OnEvasFocusIn(void *data, Evas* evas, void* event) +{ +} + +void EvasEventHandler::OnEvasFocusOut(void *data, Evas* evas, void* event) +{ +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Render callbacks +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void EvasEventHandler::OnEvasRenderPost(void *data, Evas* evas, void* event) +{ + EvasPluginEventInterface* pEvasPlugin = static_cast(data); + pEvasPlugin->OnEvasPostRender(); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Elm Access callbacks +///////////////////////////////////////////////////////////////////////////////////////////////////// + +Eina_Bool EvasEventHandler::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->OnElmAccessActionHighlight(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionUnhighlight(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionHighlightNext(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionHighlightPrev(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionActivate(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionScroll(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionUp(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionDown(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionBack(daliActionInfo); +} + +Eina_Bool EvasEventHandler::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->OnElmAccessActionRead(daliActionInfo); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// Elm Focus callbacks +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void EvasEventHandler::OnEvasObjectSmartFocused(void *data, Evas_Object* evasObject, void* event) +{ + EvasEventHandler* eventHandler = static_cast(data); + EvasPluginEventInterface& evasPlugin = eventHandler->GetEvasPluginInterface(); + + if (eventHandler->mElmFocusEvasObject == 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 + KeyEvent fakeKeyEvent("", "", 0, 0, 100, KeyEvent::Down); + + evasPlugin.OnEvasObjectKeyEvent(fakeKeyEvent); + } + } + + evas_object_focus_set(eventHandler->mImageEvasObject, EINA_TRUE); + } +} + +void EvasEventHandler::OnEvasObjectSmartUnfocused(void *data, Evas_Object* evasObject, void* event) +{ + EvasEventHandler* eventHandler = static_cast(data); + if (eventHandler->mElmFocusEvasObject == evasObject) + { + evas_object_focus_set(eventHandler->mImageEvasObject, EINA_FALSE); + } +} + +} // 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..15711f0 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-event-handler.h @@ -0,0 +1,230 @@ +#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 +#include +#include +// #include + +#include + +// INTERNAL INCLUDES +#include "evas-plugin-event-interface.h" + + + +namespace Dali +{ +template +class Rect; + +struct TouchPoint; +struct WheelEvent; +struct KeyEvent; + +namespace Extension +{ + +namespace Internal +{ + +class EvasPluginEventInterface; + +class EvasEventHandler +{ +public: + /** + * @brief Constructor + * + * @param[in] imageEvasObject is stream showing the pixmap which is drawn by dali + * + * + * @param[in] evasPluginEventInterface Used to send event to evas plugin + */ + EvasEventHandler(Evas_Object* imageEvasObject, + Evas_Object* elmAccessEvasObject, + Evas_Object* elmFocusEvasObject, + EvasPluginEventInterface& evasPluginEventInterface); + + /** + * Destructor. + */ + ~EvasEventHandler(); + +public: + + EvasPluginEventInterface& GetEvasPluginInterface() { return mEvasPluginEventInterface; } + +private: + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 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); + +private: + EvasPluginEventInterface& mEvasPluginEventInterface; + + Evas* mEvas; + Evas_Object* mImageEvasObject; + Evas_Object* mElmAccessEvasObject; + Evas_Object* mElmFocusEvasObject; +}; + +} // namespace Internal + +} // namespace Extension + +} // namespace Dali + +#endif diff --git a/dali-extension/internal/evas-plugin/evas-plugin-event-interface.h b/dali-extension/internal/evas-plugin/evas-plugin-event-interface.h new file mode 100644 index 0000000..e8b2d15 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-plugin-event-interface.h @@ -0,0 +1,151 @@ +#ifndef __DALI_EXTENSION_INTERNAL_EVAS_PLUGIN_EVENT_INTERFACE_H__ +#define __DALI_EXTENSION_INTERNAL_EVAS_PLUGIN_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. + * + */ + +namespace Dali +{ + +template +class Rect; + +struct TouchPoint; +struct WheelEvent; +struct KeyEvent; + +namespace Extension +{ + +namespace Internal +{ + +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 Handle evas object event + * + * @param[in] touchPoint is the information of touch + * @param[in] timeStamp is that touch is occured + */ + virtual void OnEvasObjectTouchEvent(TouchPoint& touchPoint, unsigned long timeStamp) = 0; + + /** + * @brief Handle evas object event + * + * @param[in] wheelEvent is the information of wheel + */ + virtual void OnEvasObjectWheelEvent(WheelEvent& wheelEvent) = 0; + + /** + * @brief Handle evas object event + * + * @param[in] keyEvent is the information of key + */ + virtual void OnEvasObjectKeyEvent(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; + + virtual bool OnElmAccessActionHighlight(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionUnhighlight(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionHighlightNext(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionHighlightPrev(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionActivate(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionScroll(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionUp(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionDown(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionBack(AccessActionInfo& accessActionInfo) = 0; + + virtual bool OnElmAccessActionRead(AccessActionInfo& accessActionInfo) = 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..0176df6 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-plugin-impl.cpp @@ -0,0 +1,664 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include "evas-plugin-impl.h" + +namespace Dali +{ + +namespace Extension +{ + +namespace Internal +{ + +namespace +{ +const char* IMAGE_EVAS_OBJECT_NAME = "dali-evas-plugin"; +const char* ELM_OBJECT_STYLE = "transparent"; +const char* ELM_OBJECT_CONTAINER_PART_NAME = "elm.swallow.content"; +} + +struct EvasPlugin::Impl +{ + Impl(EvasPlugin* evasPlugin, Evas_Object* parentEvasObject, int width, int height, bool transparent) + : mEvasPlugin(evasPlugin) + , mEcoreEvas(NULL) + , mImageEvasObject(NULL) + , mDaliAccessEvasObject(NULL) + , mDaliEvasObject(NULL) + { + Evas* evas = evas_object_evas_get(parentEvasObject); + 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 + mDaliAccessEvasObject = elm_access_object_register(mImageEvasObject, parentEvasObject); + + // Create a button and set style as "focus", if does not want to show the focus, then "transparent" + mDaliEvasObject = elm_button_add(parentEvasObject); + + // Don't need to show the focus boundary here + elm_object_style_set(mDaliEvasObject, ELM_OBJECT_STYLE); + + // Set the image evas object to focus object, but event should not be propagated + elm_object_part_content_set(mDaliEvasObject, 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(mDaliEvasObject, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(mDaliEvasObject, EVAS_HINT_FILL, EVAS_HINT_FILL); + + evas_object_move(mDaliEvasObject, 0, 0); + evas_object_resize(mDaliEvasObject, width, height); + evas_object_show(mDaliEvasObject); + } + + ~Impl() + { + // Delete the elm focus evas object + evas_object_del(mDaliEvasObject); + mDaliEvasObject = NULL; + + // Unregister elm_access_object + elm_access_object_unregister(mImageEvasObject); + mDaliAccessEvasObject = NULL; + + // Delete the image evas object + evas_object_del(mImageEvasObject); + mImageEvasObject = NULL; + } + + Ecore_Wl2_Window* GetNativeWindow() + { + return ecore_evas_wayland2_window_get( mEcoreEvas ); + } + + PositionSize GetGeometry() + { + PositionSize geometry; + evas_object_geometry_get(mImageEvasObject, &geometry.x, &geometry.y, &geometry.width, &geometry.height); + return geometry; + } + + void SetFocus() + { + evas_object_focus_set(mImageEvasObject, EINA_TRUE); + } + + void BindTBMSurface( tbm_surface_h surface ) + { +#ifdef ENABLE_TTRACE + traceBegin( TTRACE_TAG_GRAPHICS, "EvasNativeSurfaceSet[%d]", pixmap ); +#endif + + 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 ); + +#ifdef ENABLE_TTRACE + traceEnd( TTRACE_TAG_GRAPHICS ); +#endif + } + + void RequestRender() + { + evas_object_image_pixels_dirty_set( mImageEvasObject, EINA_TRUE ); + ecore_evas_manual_render( mEcoreEvas ); + } + + EvasPlugin* mEvasPlugin; + Ecore_Evas* mEcoreEvas; + Evas_Object* mImageEvasObject; + Evas_Object* mDaliAccessEvasObject; + Evas_Object* mDaliEvasObject; +}; + +EvasPluginPtr EvasPlugin::New(Evas_Object* parentEvasObject, int width, int height, bool transparent) +{ + EvasPluginPtr evasPlugin = new EvasPlugin(parentEvasObject, width, height, transparent); + return evasPlugin; +} + +EvasPlugin::EvasPlugin(Evas_Object* parentEvasObject, int width, int height, bool transparent) +: mState(READY) +, mTBMRenderSurface(NULL) +, mAdaptor(NULL) +, mRenderNotification(NULL) +, mEvasEventHandler(NULL) +, mEcoreWlEventHandler(NULL) +, mIsFocus(false) +, mTransparent(transparent) +, mImpl(NULL) +{ + DALI_ASSERT_ALWAYS( parentEvasObject && "No parent object for the evas plugin." ); + + mImpl = new Impl(this, parentEvasObject, width, height, transparent); + +#ifdef DALI_PREVENT_TIZEN_40_FEATURE + // Create the singleton service + mSingletonService = SingletonService::New(); + + // Create the pixmap render surface + mTBMRenderSurface = CreateNativeSurface( PositionSize( 0, 0, width, height ), transparent ); + + // Initialize dali + Any nativeWindow = mImpl->GetNativeWindow(); + mAdaptor = &Adaptor::New(nativeWindow, *mTBMRenderSurface, Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS); +#endif + +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER + ImfManager imfManager = ImfManager::Get(); + if(imfManager) + { + imfManager.ActivatedSignal().Connect(this, &EvasPlugin::OnImfActivated); + } +#endif + +#ifdef DALI_PREVENT_TIZEN_40_FEATURE + TriggerEventFactory triggerEventFactory; + mRenderNotification = triggerEventFactory.CreateTriggerEvent(MakeCallback(this, &EvasPlugin::OnPostRender), + TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER); + + mTBMRenderSurface->SetRenderNotification(mRenderNotification); +#endif +} + +EvasPlugin::~EvasPlugin() +{ +#ifdef DALI_PREVENT_TIZEN_40_FEATURE + mAdaptor->Stop(); + + if (mEcoreWlEventHandler) + { + delete mEcoreWlEventHandler; + mEcoreWlEventHandler = NULL; + } + + if (mEvasEventHandler) + { + delete mEvasEventHandler; + mEvasEventHandler = NULL; + } + + delete mRenderNotification; + mRenderNotification = NULL; + + // the singleton service should be unregistered before adaptor deletion + mSingletonService.UnregisterAll(); + + delete mAdaptor; + mAdaptor = NULL; + + delete mTBMRenderSurface; + mTBMRenderSurface = NULL; +#endif + + delete mImpl; + mImpl = NULL; +} + +void EvasPlugin::Run() +{ +#ifdef DALI_PREVENT_TIZEN_40_FEATURE + if(READY == mState) + { + if (!mEvasEventHandler) + { + mEvasEventHandler = new Extension::Internal::EvasEventHandler(mImpl->mImageEvasObject, mImpl->mDaliAccessEvasObject, mImpl->mDaliEvasObject, *this); + } + + // Start the adaptor + mAdaptor->Start(); + + mInitSignal.Emit(); + + mAdaptor->NotifySceneCreated(); + + mState = RUNNING; + + DALI_LOG_RELEASE_INFO("EvasPlugin::Run"); + } +#endif +} + +void EvasPlugin::Pause() +{ + if(mState == RUNNING) + { + mState = SUSPENDED; + + mAdaptor->Pause(); + + mPauseSignal.Emit(); + + DALI_LOG_RELEASE_INFO("EvasPlugin::Pause"); + } +} + +void EvasPlugin::Resume() +{ + if(mState == SUSPENDED) + { + mAdaptor->Resume(); + + mResumeSignal.Emit(); + + mState = RUNNING; + + DALI_LOG_RELEASE_INFO("EvasPlugin::Resume"); + } +} + +void EvasPlugin::Stop() +{ +#ifdef DALI_PREVENT_TIZEN_40_FEATURE + if(mState != STOPPED) + { + // Stop the adaptor + mAdaptor->Stop(); + mState = STOPPED; + + mTerminateSignal.Emit(); + + DALI_LOG_RELEASE_INFO("EvasPlugin::Stop"); + } +#endif +} + +Evas_Object* EvasPlugin::GetDaliAccessEvasObject() +{ + return mImpl->mDaliAccessEvasObject; +} + +Evas_Object* EvasPlugin::GetDaliEvasObject() +{ + return mImpl->mDaliEvasObject; +} + +void EvasPlugin::ResizeSurface() +{ +#if 0 + // Remember old surface + NativeRenderSurface* oldSurface = mTBMRenderSurface; + TriggerEventInterface* oldTriggerEvent = mRenderNotification; + + PositionSize geometry = mImpl->GetGeometry(); + + mAdaptor->SurfaceSizeChanged( geometry ); + + // emit resized signal to application + mResizeSignal.Emit(); + + mTBMRenderSurface = CreateNativeSurface( PositionSize( 0, 0, geometry.width, geometry.height ), NATIVE_SURFACE_NAME, mTransparent ); + mTBMRenderSurface->SetRenderNotification( mRenderNotification ); + + // Ask the replace the surface inside dali + Any nativeWindow = mImpl->GetNativeWindow(); + + mAdaptor->ReplaceSurface( nativeWindow, *mTBMRenderSurface ); // this method is synchronous => guarantee until rendering next frame + + TriggerEventFactory triggerEventFactory; + mRenderNotification = triggerEventFactory.CreateTriggerEvent( MakeCallback( this, &EvasPlugin::OnPostRender ), + TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ); + + mTBMRenderSurface->SetRenderNotification( mRenderNotification ); + delete oldTriggerEvent; + + // Bind offscreen surface to the evas object + mTBMRenderSurface->WaitUntilSurfaceReplaced(); + mImpl->BindTBMSurface( AnyCast( mTBMRenderSurface->GetDrawable() ) ); + mAdaptor->ReleaseSurfaceLock(); + + // It's now safe to delete the old surface + delete oldSurface; +#endif +} + +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER +void EvasPlugin::OnImfActivated(ImfManager& imfManager) +{ + mImpl->SetFocus(); +} +#endif + +void EvasPlugin::OnPostRender() +{ + // Bind offscreen surface to the evas object + mImpl->BindTBMSurface(AnyCast(mTBMRenderSurface->GetDrawable())); + mAdaptor->ReleaseSurfaceLock(); + + mImpl->RequestRender(); +} + +void EvasPlugin::OnEvasObjectTouchEvent(TouchPoint& touchPoint, unsigned long timeStamp) +{ + mAdaptor->FeedTouchPoint(touchPoint, timeStamp); +} + +void EvasPlugin::OnEvasObjectWheelEvent(WheelEvent& wheelEvent) +{ + mAdaptor->FeedWheelEvent( wheelEvent ); +} + +void EvasPlugin::OnEvasObjectKeyEvent(KeyEvent& keyEvent) +{ + mAdaptor->FeedKeyEvent( keyEvent ); +} + +void EvasPlugin::OnEvasObjectMove(const Rect& geometry) +{ +} + +void EvasPlugin::OnEvasObjectResize(const Rect& geometry) +{ + DALI_LOG_RELEASE_INFO("EvasPlugin::OnEvasObjectResize (%d x %d)", geometry.width, geometry.height); + + if (geometry.width <= 1 || geometry.height <= 1) + { + // skip meaningless resize signal + return; + } + + Vector2 size = Stage::GetCurrent().GetSize(); + if(size.width == geometry.width && size.height == geometry.height) + { + // skip meaningless resize signal + return; + } + + ResizeSurface(); +} + +void EvasPlugin::OnEvasObjectFocusIn() +{ + if(!mIsFocus) + { + if (!mEcoreWlEventHandler) + { + mEcoreWlEventHandler = new Extension::Internal::EcoreWlEventHandler(mImpl->GetNativeWindow(), *this); + } + +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER + ImfManager imfManager = ImfManager::Get(); + if(imfManager) + { + // TODO : Move to Impl + Ecore_Wl_Window* window = mImpl->GetNativeWindow(); + Ecore_IMF_Context* imfContext = Dali::Internal::Adaptor::ImfManager::GetImplementation(imfManager).GetContext(); + ecore_imf_context_client_window_set( imfContext, reinterpret_cast( window ) ); + + if(imfManager.RestoreAfterFocusLost()) + { + imfManager.Activate(); + } + } +#endif + + mFocusedSignal.Emit(); + + mIsFocus = true; + + DALI_LOG_RELEASE_INFO("EvasPlugin::OnEvasObjectFocusIn"); + } +} + +void EvasPlugin::OnEvasObjectFocusOut() +{ + if(mIsFocus) + { + mIsFocus = false; + + if (mEcoreWlEventHandler) + { + delete mEcoreWlEventHandler; + mEcoreWlEventHandler = NULL; + } + +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER + ImfManager imfManager = ImfManager::Get(); + if(imfManager && imfManager.RestoreAfterFocusLost()) + { + imfManager.Deactivate(); + } +#endif + + Clipboard::Get().HideClipboard(); + + mUnFocusedSignal.Emit(); + + DALI_LOG_RELEASE_INFO("EvasPlugin::OnEvasObjectFocusOut"); + } +} + +void EvasPlugin::OnEvasPostRender() +{ +} + +bool EvasPlugin::OnElmAccessActionHighlight(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +bool EvasPlugin::OnElmAccessActionUnhighlight(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +bool EvasPlugin::OnElmAccessActionHighlightNext(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +bool EvasPlugin::OnElmAccessActionHighlightPrev(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +bool EvasPlugin::OnElmAccessActionActivate(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +bool EvasPlugin::OnElmAccessActionUp(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +bool EvasPlugin::OnElmAccessActionDown(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +bool EvasPlugin::OnElmAccessActionScroll(AccessActionInfo& accessActionInfo) +{ + bool ret = false; + + Evas_Coord rel_x, rel_y; + Evas_Coord obj_x, obj_y, obj_w, obj_h; + Evas_Object* eo = this->GetDaliAccessEvasObject(); + + if(eo) + { + 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; + + ret = this->OnElmAccessibilityActionEvent(accessActionInfo, rel_x, rel_y); + } + + return ret; +} + +bool EvasPlugin::OnElmAccessActionBack(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +bool EvasPlugin::OnElmAccessActionRead(AccessActionInfo& accessActionInfo) +{ + return this->OnElmAccessibilityActionEvent(accessActionInfo); +} + +void EvasPlugin::OnEcoreWlVisibility(bool visibility) +{ + if (!visibility) + { + mAdaptor->ReleaseSurfaceLock(); + } +} + +bool EvasPlugin::OnElmAccessibilityActionEvent(AccessActionInfo& accessActionInfo, int x, int y) +{ + bool ret = false; + + if( NULL == mAdaptor) + { + return ret; + } + + Dali::AccessibilityAdaptor accessibilityAdaptor = Dali::AccessibilityAdaptor::Get(); + if( accessibilityAdaptor ) + { + int touchType = accessActionInfo.mouseType; + int touchX = x >= 0 ? x : accessActionInfo.x; + int touchY = y >= 0 ? y : accessActionInfo.y; + + switch(accessActionInfo.actionBy) + { + case Dali::Extension::Internal::ACCESS_ACTION_HIGHLIGHT: + case Dali::Extension::Internal::ACCESS_ACTION_READ: + { + ret = accessibilityAdaptor.HandleActionReadEvent((unsigned int)x, (unsigned int)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: + { + 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. + TouchPoint point( 0, state, (float)touchX, (float)touchY ); + 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__); + } + + DALI_LOG_INFO(gEvasPluginLogFilter, Debug::General, "[%s:%d] [action : %d] focus manager returns %s\n", __FUNCTION__, __LINE__, (int)(actionType), ret?"TRUE":"FALSE"); + + return ret; +} + +} // 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..39925f6 --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-plugin-impl.h @@ -0,0 +1,393 @@ +#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 +#include +#include +#include + +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER +#include +#endif + +#include + + +#ifdef ENABLE_TTRACE +#include +#endif + + +// INTERNAL INCLUDES +#include "evas-event-handler.h" +#include "ecore-wl-event-handler.h" +#include "evas-plugin-event-interface.h" +#include "evas-plugin-visibility-interface.h" + +#include + +namespace Dali +{ +class TriggerEventInterface; +class NativeRenderSurface; + +namespace Extension +{ + +namespace Internal +{ + +typedef Rect PositionSize; + +class EvasPlugin; +typedef IntrusivePtr EvasPluginPtr; + +/** + * Implementation of the EvasPlugin class. + */ +class EvasPlugin : public BaseObject, + public ConnectionTracker, + public Extension::Internal::EvasPluginEventInterface, + public Extension::Internal::EvasPluginVisibilityInterface +{ +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] transparent Whether the evas object is transparent or not + */ + static EvasPluginPtr New(Evas_Object* parentEvasObject, int width, int height, bool transparent); + +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(); + + /** + * @copydoc Dali::Extension::EvasPlugin::GetDaliAccessEvasObject() + */ + Evas_Object* GetDaliAccessEvasObject(); + + /** + * @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; + } + +private: + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectTouchEvent + */ + virtual void OnEvasObjectTouchEvent(TouchPoint& touchPoint, unsigned long timeStamp); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectWheelEvent + */ + virtual void OnEvasObjectWheelEvent(WheelEvent& wheelEvent); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectKeyEvent + */ + virtual void OnEvasObjectKeyEvent(KeyEvent& keyEvent); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectMove + */ + virtual void OnEvasObjectMove(const Rect& geometry); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectResize + */ + virtual void OnEvasObjectResize(const Rect& geometry); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectFocusIn + */ + virtual void OnEvasObjectFocusIn(); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasObjectFocusOut + */ + virtual void OnEvasObjectFocusOut(); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnEvasRenderPost + */ + virtual void OnEvasPostRender(); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionHighlight + */ + virtual bool OnElmAccessActionHighlight(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionUnhighlight + */ + virtual bool OnElmAccessActionUnhighlight(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionHighlightNext + */ + virtual bool OnElmAccessActionHighlightNext(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionHighlightPrev + */ + virtual bool OnElmAccessActionHighlightPrev(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionActivate + */ + virtual bool OnElmAccessActionActivate(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionUp + */ + virtual bool OnElmAccessActionUp(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionDown + */ + virtual bool OnElmAccessActionDown(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionScroll + */ + virtual bool OnElmAccessActionScroll(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface:OnElmAccessActionBack: + */ + virtual bool OnElmAccessActionBack(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginEventInterface::OnElmAccessActionRead + */ + virtual bool OnElmAccessActionRead(Dali::Extension::Internal::AccessActionInfo& accessActionInfo); + + /** + * @copydoc Dali::Extension::Internal::EvasPluginVisibilityInterface::OnElmEcoreWlVisibility + */ + virtual void OnEcoreWlVisibility(bool visibility); + + /** + * Resize the surface + * To resize, create new surface with evas object's size and replace with it. + */ + void ResizeSurface(); + +#ifdef DALI_EVASPLUGIN_USE_IMF_MANAGER + /** + * For ImfActivated signal + * When the imf is activated, it will handle the focus + * @param[in] imfManager imfManager instance + */ + void OnImfActivated(ImfManager& imfManager); +#endif + + /** + * This function is called after drawing by dali. + */ + void OnPostRender(); + + /** + * Called when the accessibility action event dispatched from elm_access. + * @param[in] actionType elm accessibility action type structure + * @param[in] x x position for action, it could be unnecessary + * @param[in] y y position for action, it could be unnecessary + * @return True if the event was handled + */ + bool OnElmAccessibilityActionEvent(AccessActionInfo& actionInfo, int x = -1, int y = -1); + +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] transparent Whether the evas object is transparent or not + */ + EvasPlugin(Evas_Object* parentEvasObject, int width, int height, bool transparent); + + /** + * Destructor + */ + virtual ~EvasPlugin(); + + // Undefined + EvasPlugin(const EvasPlugin&); + EvasPlugin& operator=(EvasPlugin&); + +private: + enum State + { + READY, + RUNNING, + SUSPENDED, + STOPPED, + }; + + State mState; + NativeRenderSurface* mTBMRenderSurface; + Adaptor* mAdaptor; + TriggerEventInterface* mRenderNotification; + Extension::Internal::EvasEventHandler* mEvasEventHandler; + Extension::Internal::EcoreWlEventHandler* mEcoreWlEventHandler; + + bool mIsFocus:1; ///< Flag + bool mTransparent:1; ///< Whether + + SingletonService mSingletonService; + + // Signals + EvasPluginSignalType mInitSignal; + EvasPluginSignalType mTerminateSignal; + EvasPluginSignalType mPauseSignal; + EvasPluginSignalType mResumeSignal; + EvasPluginSignalType mResizeSignal; + EvasPluginSignalType mFocusedSignal; + EvasPluginSignalType mUnFocusedSignal; + + struct Impl; + Impl* mImpl; +}; + +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-plugin-visibility-interface.h b/dali-extension/internal/evas-plugin/evas-plugin-visibility-interface.h new file mode 100644 index 0000000..124906b --- /dev/null +++ b/dali-extension/internal/evas-plugin/evas-plugin-visibility-interface.h @@ -0,0 +1,46 @@ +#ifndef __DALI_EXTENSION_INTERNAL_EVAS_PLUGIN_VISIBILITY_INTERFACE__ +#define __DALI_EXTENSION_INTERNAL_EVAS_PLUGIN_VISIBILITY_INTERFACE__ + +/* + * 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. + * + */ + +namespace Dali +{ + +namespace Extension +{ + +namespace Internal +{ + +class EvasPluginVisibilityInterface +{ +public: + /** + * @brief Process the ecore wayland visibility. + * + * @param[in] visibility True is that ecore wayland window is show up and false is not + */ + virtual void OnEcoreWlVisibility(bool visibility) = 0; +}; + +} // namespace Internal + +} // namespace Extension + +} // namespace Dali +#endif diff --git a/dali-extension/internal/evas-plugin/file.list b/dali-extension/internal/evas-plugin/file.list new file mode 100644 index 0000000..defd2a2 --- /dev/null +++ b/dali-extension/internal/evas-plugin/file.list @@ -0,0 +1,11 @@ +evas_plugin_internal_header_files = \ + $(extension_src_dir)/internal/evas-plugin/ecore-wl-event-handler.h \ + $(extension_src_dir)/internal/evas-plugin/evas-event-handler.h \ + $(extension_src_dir)/internal/evas-plugin/evas-plugin-event-interface.h \ + $(extension_src_dir)/internal/evas-plugin/evas-plugin-visibility-interface.h \ + $(extension_src_dir)/internal/evas-plugin/evas-plugin-impl.h + +evas_plugin_internal_src_files = \ + $(extension_src_dir)/internal/evas-plugin/ecore-wl-event-handler.cpp \ + $(extension_src_dir)/internal/evas-plugin/evas-event-handler.cpp \ + $(extension_src_dir)/internal/evas-plugin/evas-plugin-impl.cpp diff --git a/packaging/dali-extension.spec b/packaging/dali-extension.spec index d5956a8..e749a86 100755 --- a/packaging/dali-extension.spec +++ b/packaging/dali-extension.spec @@ -23,6 +23,13 @@ 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 +314,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