From: Daekwang Ryu Date: Tue, 24 Apr 2018 06:40:32 +0000 (+0900) Subject: [Tizen] ecore-wl2: applying ecore-wl2 X-Git-Tag: accepted/tizen/unified/20180426.062511~5 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git;a=commitdiff_plain;h=b08a8d097f77d5e3acb07699f4971758b7219182 [Tizen] ecore-wl2: applying ecore-wl2 This reverts commit 7703b81807140ae82b87a5ae4adf79c8f0456ad4. Change-Id: I15233e3e597d9f1108b3044c739bc54b44bfd036 --- diff --git a/build/tizen/adaptor/Makefile.am b/build/tizen/adaptor/Makefile.am index 79e3cac..190aab1 100644 --- a/build/tizen/adaptor/Makefile.am +++ b/build/tizen/adaptor/Makefile.am @@ -94,7 +94,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_adaptor_tizen_src_files) \ $(adaptor_adaptor_tizen_wayland_src_files) \ $(adaptor_clipboard_common_src_files) \ - $(adaptor_clipboard_tizen_wayland_src_files) \ $(devel_api_src_files) \ $(adaptor_devel_api_text_abstraction_src_files) \ $(adaptor_graphics_common_src_files) \ @@ -104,7 +103,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_imaging_common_src_files) \ $(adaptor_imaging_tizen_src_files) \ $(adaptor_input_common_src_files) \ - $(adaptor_input_tizen_wayland_src_files) \ $(adaptor_legacy_common_src_files) \ $(adaptor_network_common_src_files) \ $(adaptor_public_api_src_files) \ @@ -120,12 +118,23 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_window_system_common_src_files) \ $(adaptor_window_system_tizen_mobile_src_files) \ $(adaptor_window_system_tizen_src_files) \ - $(adaptor_window_system_tizen_wayland_src_files) \ $(adaptor_trace_common_src_files) \ $(devel_api_text_abstraction_src_files) \ $(static_libraries_glyphy_src_files) \ $(static_libraries_libunibreak_src_files) +if USE_ECORE_WAYLAND2 +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland2_src_files) \ + $(adaptor_input_tizen_wayland2_src_files) \ + $(adaptor_window_system_tizen_wayland2_src_files) +else +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland_src_files) \ + $(adaptor_input_tizen_wayland_src_files) \ + $(adaptor_window_system_tizen_wayland_src_files) +endif + if ENABLE_NETWORK_LOGGING LIBDALI_ADAPTOR_LA_SOURCES += \ $(adaptor_performance_logging_src_files) @@ -148,7 +157,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_adaptor_tizen_src_files) \ $(adaptor_adaptor_tizen_wayland_src_files) \ $(adaptor_clipboard_common_src_files) \ - $(adaptor_clipboard_tizen_wayland_src_files) \ $(devel_api_src_files) \ $(adaptor_devel_api_text_abstraction_src_files) \ $(adaptor_graphics_common_src_files) \ @@ -159,7 +167,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_imaging_common_src_files) \ $(adaptor_imaging_tizen_src_files) \ $(adaptor_input_common_src_files) \ - $(adaptor_input_tizen_wayland_src_files) \ $(adaptor_legacy_common_src_files) \ $(adaptor_network_common_src_files) \ $(adaptor_public_api_src_files) \ @@ -174,12 +181,23 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_web_engine_common_src_files) \ $(adaptor_window_system_common_src_files) \ $(adaptor_window_system_tizen_src_files) \ - $(adaptor_window_system_tizen_wayland_src_files) \ $(adaptor_trace_common_src_files) \ $(devel_api_text_abstraction_src_files) \ $(static_libraries_glyphy_src_files) \ $(static_libraries_libunibreak_src_files) +if USE_ECORE_WAYLAND2 +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland2_src_files) \ + $(adaptor_input_tizen_wayland2_src_files) \ + $(adaptor_window_system_tizen_wayland2_src_files) +else +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland_src_files) \ + $(adaptor_input_tizen_wayland_src_files) \ + $(adaptor_window_system_tizen_wayland_src_files) +endif + if ENABLE_NETWORK_LOGGING LIBDALI_ADAPTOR_LA_SOURCES += \ $(adaptor_performance_logging_src_files) @@ -202,7 +220,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_adaptor_tizen_src_files) \ $(adaptor_adaptor_tizen_wayland_src_files) \ $(adaptor_clipboard_common_src_files) \ - $(adaptor_clipboard_tizen_wayland_src_files) \ $(devel_api_src_files) \ $(adaptor_devel_api_text_abstraction_src_files) \ $(adaptor_graphics_common_src_files) \ @@ -212,7 +229,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_imaging_common_src_files) \ $(adaptor_imaging_tizen_src_files) \ $(adaptor_input_common_src_files) \ - $(adaptor_input_tizen_wayland_src_files) \ $(adaptor_legacy_common_src_files) \ $(adaptor_network_common_src_files) \ $(adaptor_public_api_src_files) \ @@ -227,12 +243,23 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_web_engine_common_src_files) \ $(adaptor_window_system_common_src_files) \ $(adaptor_window_system_tizen_src_files) \ - $(adaptor_window_system_tizen_wayland_src_files) \ $(adaptor_trace_common_src_files) \ $(devel_api_text_abstraction_src_files) \ $(static_libraries_glyphy_src_files) \ $(static_libraries_libunibreak_src_files) +if USE_ECORE_WAYLAND2 +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland2_src_files) \ + $(adaptor_input_tizen_wayland2_src_files) \ + $(adaptor_window_system_tizen_wayland2_src_files) +else +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland_src_files) \ + $(adaptor_input_tizen_wayland_src_files) \ + $(adaptor_window_system_tizen_wayland_src_files) +endif + if ENABLE_NETWORK_LOGGING LIBDALI_ADAPTOR_LA_SOURCES += \ $(adaptor_performance_logging_src_files) @@ -254,7 +281,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_adaptor_tizen_src_files) \ $(adaptor_adaptor_tizen_wayland_src_files) \ $(adaptor_clipboard_common_src_files) \ - $(adaptor_clipboard_tizen_wayland_src_files) \ $(devel_api_src_files) \ $(adaptor_devel_api_text_abstraction_src_files) \ $(adaptor_graphics_common_src_files) \ @@ -264,7 +290,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_imaging_common_src_files) \ $(adaptor_imaging_tizen_src_files) \ $(adaptor_input_common_src_files) \ - $(adaptor_input_tizen_wayland_src_files) \ $(adaptor_legacy_common_src_files) \ $(adaptor_network_common_src_files) \ $(adaptor_public_api_src_files) \ @@ -279,12 +304,23 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_web_engine_common_src_files) \ $(adaptor_window_system_common_src_files) \ $(adaptor_window_system_tizen_src_files) \ - $(adaptor_window_system_tizen_wayland_src_files) \ $(adaptor_trace_common_src_files) \ $(devel_api_text_abstraction_src_files) \ $(static_libraries_glyphy_src_files) \ $(static_libraries_libunibreak_src_files) +if USE_ECORE_WAYLAND2 +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland2_src_files) \ + $(adaptor_input_tizen_wayland2_src_files) \ + $(adaptor_window_system_tizen_wayland2_src_files) +else +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland_src_files) \ + $(adaptor_input_tizen_wayland_src_files) \ + $(adaptor_window_system_tizen_wayland_src_files) +endif + if ENABLE_NETWORK_LOGGING LIBDALI_ADAPTOR_LA_SOURCES += \ $(adaptor_performance_logging_src_files) @@ -309,7 +345,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_adaptor_tizen_wayland_src_files) \ $(adaptor_adaptor_tizen_wearable_src_files) \ $(adaptor_clipboard_common_src_files) \ - $(adaptor_clipboard_tizen_wayland_src_files) \ $(devel_api_src_files) \ $(adaptor_devel_api_text_abstraction_src_files) \ $(adaptor_graphics_common_src_files) \ @@ -319,7 +354,6 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_imaging_common_src_files) \ $(adaptor_imaging_tizen_src_files) \ $(adaptor_input_common_src_files) \ - $(adaptor_input_tizen_wayland_src_files) \ $(adaptor_legacy_common_src_files) \ $(adaptor_network_common_src_files) \ $(adaptor_public_api_src_files) \ @@ -334,13 +368,24 @@ LIBDALI_ADAPTOR_LA_SOURCES = \ $(adaptor_web_engine_common_src_files) \ $(adaptor_window_system_common_src_files) \ $(adaptor_window_system_tizen_src_files) \ - $(adaptor_window_system_tizen_wayland_src_files) \ $(adaptor_window_system_tizen_wearable_src_files) \ $(adaptor_trace_common_src_files) \ $(devel_api_text_abstraction_src_files) \ $(static_libraries_glyphy_src_files) \ $(static_libraries_libunibreak_src_files) +if USE_ECORE_WAYLAND2 +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland2_src_files) \ + $(adaptor_input_tizen_wayland2_src_files) \ + $(adaptor_window_system_tizen_wayland2_src_files) +else +LIBDALI_ADAPTOR_LA_SOURCES += \ + $(adaptor_clipboard_tizen_wayland_src_files) \ + $(adaptor_input_tizen_wayland_src_files) \ + $(adaptor_window_system_tizen_wayland_src_files) +endif + if ENABLE_NETWORK_LOGGING LIBDALI_ADAPTOR_LA_SOURCES += \ $(adaptor_performance_logging_src_files) @@ -567,7 +612,11 @@ tizenadaptorintegrationapi_HEADERS = $(adaptor_integration_api_header_files) if WAYLAND tizenadaptorintegrationwaylandapidir = $(devincludepath)/dali/integration-api/adaptors -tizenadaptorintegrationwaylandapi_HEADERS = $(adaptor_integration_wayland_api_header_files) +if USE_ECORE_WAYLAND2 +tizenadaptorintegrationwaylandapi_HEADERS = $(adaptor_integration_ecore_wl2_api_header_files) +else +tizenadaptorintegrationwaylandapi_HEADERS = $(adaptor_integration_ecore_wl_api_header_files) +endif tizenadaptorintegrationwaylandapi_HEADERS += $(adaptor_integration_ecore_wayland_api_header_files) else tizenadaptorintegrationx11apidir = $(devincludepath)/dali/integration-api/adaptors diff --git a/build/tizen/adaptor/configure.ac b/build/tizen/adaptor/configure.ac index 6cff84b..d149fa8 100644 --- a/build/tizen/adaptor/configure.ac +++ b/build/tizen/adaptor/configure.ac @@ -301,7 +301,9 @@ if test "x$enable_wayland" = "xyes"; then PKG_CHECK_MODULES(WAYLAND, [ecore-wayland egl wayland-egl wayland-client >= 1.2.0 xkbcommon libtbm], [DALI_USE_ECORE_WAYLAND=1], [DALI_USE_ECORE_WAYLAND=0]) - +PKG_CHECK_MODULES(WAYLAND2, [ecore-wl2 egl wayland-egl wayland-client >= 1.2.0 xkbcommon libtbm], + [DALI_USE_ECORE_WAYLAND2=1], + [DALI_USE_ECORE_WAYLAND2=0]) else PKG_CHECK_MODULES(ECORE_X, [ecore-x], [DALI_USE_ECORE_X11=1], @@ -319,6 +321,7 @@ PKG_CHECK_MODULES(WAYLAND_EXTENSION, xdg-shell-client text-client input-method-c fi fi AM_CONDITIONAL([USE_ECORE_WAYLAND], [test "$DALI_USE_ECORE_WAYLAND" -eq 1]) +AM_CONDITIONAL([USE_ECORE_WAYLAND2], [test "$DALI_USE_ECORE_WAYLAND2" -eq 1]) if test x$DALI_DATA_RW_DIR != x; then dataReadWriteDir=$DALI_DATA_RW_DIR diff --git a/dali/integration-api/file.list b/dali/integration-api/file.list index 9100a28..68397fe 100644 --- a/dali/integration-api/file.list +++ b/dali/integration-api/file.list @@ -7,9 +7,15 @@ adaptor_integration_api_header_files = \ $(adaptor_integration_api_dir)/trigger-event-factory-interface.h \ $(adaptor_integration_api_dir)/trigger-event-factory.h -adaptor_integration_wayland_api_header_files = \ +adaptor_integration_ecore_wl_api_header_files = \ $(adaptor_integration_api_dir)/wayland/wl-types.h \ - $(adaptor_integration_api_dir)/wayland/ecore-wl-render-surface.h \ + $(adaptor_integration_api_dir)/wayland/ecore-wl/ecore-wl-render-surface.h \ + $(adaptor_integration_api_dir)/wayland/native-render-surface.h \ + $(adaptor_integration_api_dir)/native-render-surface-factory.h + +adaptor_integration_ecore_wl2_api_header_files = \ + $(adaptor_integration_api_dir)/wayland/wl-types.h \ + $(adaptor_integration_api_dir)/wayland/ecore-wl2/ecore-wl2-render-surface.h \ $(adaptor_integration_api_dir)/wayland/native-render-surface.h \ $(adaptor_integration_api_dir)/native-render-surface-factory.h diff --git a/dali/integration-api/wayland/ecore-wl-render-surface.h b/dali/integration-api/wayland/ecore-wl/ecore-wl-render-surface.h similarity index 100% rename from dali/integration-api/wayland/ecore-wl-render-surface.h rename to dali/integration-api/wayland/ecore-wl/ecore-wl-render-surface.h diff --git a/dali/integration-api/wayland/pixmap-render-surface.h b/dali/integration-api/wayland/ecore-wl/pixmap-render-surface.h similarity index 98% rename from dali/integration-api/wayland/pixmap-render-surface.h rename to dali/integration-api/wayland/ecore-wl/pixmap-render-surface.h index f2a7815..9e02e41 100644 --- a/dali/integration-api/wayland/pixmap-render-surface.h +++ b/dali/integration-api/wayland/ecore-wl/pixmap-render-surface.h @@ -19,7 +19,7 @@ */ // INTERNAL INCLUDES -#include +#include namespace Dali { diff --git a/dali/integration-api/wayland/ecore-wl2/ecore-wl2-render-surface.h b/dali/integration-api/wayland/ecore-wl2/ecore-wl2-render-surface.h new file mode 100644 index 0000000..df9ed43 --- /dev/null +++ b/dali/integration-api/wayland/ecore-wl2/ecore-wl2-render-surface.h @@ -0,0 +1,193 @@ +#ifndef __DALI_ECORE_WL2_RENDER_SURFACE_H__ +#define __DALI_ECORE_WL2_RENDER_SURFACE_H__ + +/* + * Copyright (c) 2017 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 + +// INTERNAL INCLUDES +#include +#ifdef DALI_ADAPTOR_COMPILATION // full path doesn't exist until adaptor is installed so we have to use relative +#include +#else +#include +#endif + +namespace Dali +{ + +class TriggerEventInterface; + +namespace ECore +{ + +/** + * Ecore Wayland implementation of render surface. + * @todo change namespace to ECore_Wayland as the class + * is no longer pure Wayland. + */ +class DALI_IMPORT_API EcoreWlRenderSurface : public Dali::RenderSurface +{ +public: + /** + * Uses an Wayland surface to render to. + * @param [in] positionSize the position and size of the surface + * @param [in] surface can be a X-window or X-pixmap (type must be unsigned int). + * @param [in] name optional name of surface passed in + * @param [in] isTransparent if it is true, surface has 32 bit color depth, otherwise, 24 bit + */ + EcoreWlRenderSurface(Dali::PositionSize positionSize, + Any surface, + const std::string& name, + bool isTransparent = false); + + /** + * Destructor. + * Will delete the display, if it has ownership. + * Will delete the window/pixmap if it has owner ship + */ + virtual ~EcoreWlRenderSurface(); + +protected: + /** + * Second stage construction + * Creates the surface (window, pixmap or native buffer) + */ + void Init( Any surface ); + +public: // API + + /** + * @brief Sets the render notification trigger to call when render thread is completed a frame + * + * @param renderNotification to use + */ + void SetRenderNotification(TriggerEventInterface* renderNotification); + + /** + * @brief Get window handle + * + * @return the Ecore X window handle + */ + virtual Ecore_Wl2_Window* GetWlWindow(); + + /** + * Get the surface as an Ecore_Wl2_Window + */ + virtual Ecore_Wl2_Window* GetDrawable(); + +public: // from Dali::RenderSurface + + /** + * @copydoc Dali::RenderSurface::GetPositionSize() + */ + virtual PositionSize GetPositionSize() const; + + /** + * @copydoc Dali::RenderSurface::InitializeEgl() + */ + virtual void InitializeEgl( EglInterface& egl ) = 0; + + /** + * @copydoc Dali::RenderSurface::CreateEglSurface() + */ + virtual void CreateEglSurface( EglInterface& egl ) = 0; + + /** + * @copydoc Dali::RenderSurface::DestroyEglSurface() + */ + virtual void DestroyEglSurface( EglInterface& egl ) = 0; + + /** + * @copydoc Dali::RenderSurface::ReplaceEGLSurface() + */ + virtual bool ReplaceEGLSurface( EglInterface& egl ) = 0; + + /** + * @copydoc Dali::RenderSurface::MoveResize() + */ + virtual void MoveResize( Dali::PositionSize positionSize); + + /** + * @copydoc Dali::RenderSurface::SetViewMode() + */ + void SetViewMode( ViewMode viewMode ); + + /** + * @copydoc Dali::RenderSurface::StartRender() + */ + virtual void StartRender() = 0; + + /** + * @copydoc Dali::RenderSurface::PreRender() + */ + virtual bool PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface ) = 0; + + /** + * @copydoc Dali::RenderSurface::PostRender() + */ + virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface ) = 0; + + /** + * @copydoc Dali::RenderSurface::ReleaseLock() + */ + virtual void ReleaseLock() = 0; + + /** + * @copydoc Dali::RenderSurface::GetSurfaceType() + */ + virtual RenderSurface::Type GetSurfaceType(); + +private: + + /** + * Get the surface id if the surface parameter is not empty + * @param surface Any containing a surface id, or can be empty + * @return surface id, or zero if surface is empty + */ + unsigned int GetSurfaceId( Any surface ) const; + +protected: + + /** + * Create XRenderable + */ + virtual void CreateWlRenderable() = 0; + + /** + * Use an existing render surface + * @param surfaceId the id of the surface + */ + virtual void UseExistingRenderable( unsigned int surfaceId ) = 0; + +protected: // Data + + PositionSize mPositionSize; ///< Position + std::string mTitle; ///< Title of window which shows from "xinfo -topvwins" command + TriggerEventInterface* mRenderNotification; ///< Render notification trigger + ColorDepth mColorDepth; ///< Color depth of surface (32 bit or 24 bit) + bool mOwnSurface; ///< Whether we own the surface (responsible for deleting it) +}; + +} // namespace ECore + +} // namespace Dali + +#endif // __DALI_ECORE_WL2_RENDER_SURFACE_H__ diff --git a/dali/integration-api/wayland/ecore-wl2/pixmap-render-surface2.h b/dali/integration-api/wayland/ecore-wl2/pixmap-render-surface2.h new file mode 100644 index 0000000..9544a2d --- /dev/null +++ b/dali/integration-api/wayland/ecore-wl2/pixmap-render-surface2.h @@ -0,0 +1,158 @@ +#ifndef __DALI_ECORE_X_PIXMAP_RENDER_SURFACE_H__ +#define __DALI_ECORE_X_PIXMAP_RENDER_SURFACE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace ECore +{ + +/** + * Ecore X11 implementation of render surface. + */ +class PixmapRenderSurface : public EcoreWlRenderSurface +{ +public: + + /** + * Uses an Wayland surface to render to. + * @param [in] positionSize the position and size of the surface + * @param [in] surface can be a Wayland-window (type must be unsigned int). + * @param [in] name optional name of surface passed in + * @param [in] isTransparent if it is true, surface has 32 bit color depth, otherwise, 24 bit + */ + PixmapRenderSurface( Dali::PositionSize positionSize, + Any surface, + const std::string& name, + bool isTransparent = false); + + /** + * @copydoc Dali::RenderSurface::~RenderSurface + */ + virtual ~PixmapRenderSurface(); + +public: // API + + /** + * @copydoc Dali::ECore::EcoreWlRenderSurface::GetDrawable() + */ + virtual Ecore_Wl2_Window* GetDrawable(); + + /** + * @brief GetSurface + * + * @return pixmap + */ + virtual Any GetSurface(); + +public: // from Dali::RenderSurface + + /** + * @copydoc Dali::RenderSurface::InitializeEgl() + */ + virtual void InitializeEgl( EglInterface& egl ); + + /** + * @copydoc Dali::RenderSurface::CreateEglSurface() + */ + virtual void CreateEglSurface( EglInterface& egl ); + + /** + * @copydoc Dali::RenderSurface::DestroyEglSurface() + */ + virtual void DestroyEglSurface( EglInterface& egl ); + + /** + * @copydoc Dali::RenderSurface::ReplaceEGLSurface() + */ + virtual bool ReplaceEGLSurface( EglInterface& egl ); + + /** + * @copydoc Dali::RenderSurface::StartRender() + */ + virtual void StartRender(); + + /** + * @copydoc Dali::RenderSurface::PreRender() + */ + virtual bool PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface ); + + /** + * @copydoc Dali::RenderSurface::PostRender() + */ + virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface ); + + /** + * @copydoc Dali::RenderSurface::StopRender() + */ + virtual void StopRender(); + + /** + * @copydoc Dali::RenderSurface::SetThreadSynchronization + */ + virtual void SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization ); + +private: + enum SyncMode + { + SYNC_MODE_NONE, + SYNC_MODE_WAIT + }; + + /** + * Set the sync mode. + * @param[in] syncMode The sync mode + */ + void SetSyncMode( SyncMode syncMode ); + + /** + * If sync mode is WAIT, then acquire a lock. This prevents render thread from + * continuing until the pixmap has been drawn by the compositor. + * It must be released for rendering to continue. + */ + void AcquireLock(); + + /** + * Release any locks. + */ + void ReleaseLock(); + + /** + * Create XPixmap + */ + virtual void CreateWlRenderable(); + + /** + * @copydoc Dali::Internal::Adaptor::ECore::RenderSurface::UseExistingRenderable + */ + virtual void UseExistingRenderable( unsigned int surfaceId ); + +private: // Data + +}; + +} // namespace ECore + +} // namespace Dali + +#endif // __DALI_ECORE_X_PIXMAP_RENDER_SURFACE_H__ diff --git a/dali/internal/adaptor/common/adaptor-impl.cpp b/dali/internal/adaptor/common/adaptor-impl.cpp index 9d8adc1..3fa8e3f 100644 --- a/dali/internal/adaptor/common/adaptor-impl.cpp +++ b/dali/internal/adaptor/common/adaptor-impl.cpp @@ -304,7 +304,11 @@ void Adaptor::Start() unsigned int dpiHor, dpiVer; dpiHor = dpiVer = 0; - Dali::DisplayConnection::GetDpi(dpiHor, dpiVer); +#ifdef ECORE_WL2 + Dali::DisplayConnection::GetDpi( mNativeWindow, dpiHor, dpiVer ); +#else + Dali::DisplayConnection::GetDpi( dpiHor, dpiVer ); +#endif // tell core about the DPI value mCore->SetDpi(dpiHor, dpiVer); diff --git a/dali/internal/adaptor/tizen/adaptor-impl-tizen.cpp b/dali/internal/adaptor/tizen/adaptor-impl-tizen.cpp old mode 100644 new mode 100755 index 35dbcea..7df70ea --- a/dali/internal/adaptor/tizen/adaptor-impl-tizen.cpp +++ b/dali/internal/adaptor/tizen/adaptor-impl-tizen.cpp @@ -22,7 +22,11 @@ #include #ifdef APPCORE_WATCH_AVAILABLE #include -#include +#ifdef ECORE_WL2 +#include +#else +#include +#endif #endif #include @@ -106,8 +110,13 @@ void Adaptor::SurfaceInitialized() // Use strdup() in app_get_id(), so need to free memory if( appId ) { +#ifdef ECORE_WL2 + Ecore_Wl2_Window* ecoreWlWindow = AnyCast( mNativeWindow ); + screen_connector_provider_remote_enable(appId, ecore_wl2_window_surface_get(ecoreWlWindow)); +#else Ecore_Wl_Window* ecoreWlWindow = AnyCast( mNativeWindow ); screen_connector_provider_remote_enable(appId, ecore_wl_window_surface_get(ecoreWlWindow)); +#endif free( appId ); } #endif diff --git a/dali/internal/clipboard/file.list b/dali/internal/clipboard/file.list index a6c2190..1806e5d 100644 --- a/dali/internal/clipboard/file.list +++ b/dali/internal/clipboard/file.list @@ -5,8 +5,11 @@ adaptor_clipboard_common_src_files=\ ${adaptor_clipboard_dir}/common/clipboard-event-notifier-impl.cpp # module: clipboard, backend: tizen-wayland +adaptor_clipboard_tizen_wayland2_src_files=\ + ${adaptor_clipboard_dir}/tizen-wayland/ecore-wl2/clipboard-impl-ecore-wl2.cpp + adaptor_clipboard_tizen_wayland_src_files=\ - ${adaptor_clipboard_dir}/tizen-wayland/clipboard-impl-ecore-wl.cpp + ${adaptor_clipboard_dir}/tizen-wayland/ecore-wl/clipboard-impl-ecore-wl.cpp # module: clipboard, backend: ubuntu-x11 adaptor_clipboard_ubuntu_x11_src_files=\ diff --git a/dali/internal/clipboard/tizen-wayland/clipboard-impl-ecore-wl.cpp b/dali/internal/clipboard/tizen-wayland/ecore-wl/clipboard-impl-ecore-wl.cpp similarity index 100% rename from dali/internal/clipboard/tizen-wayland/clipboard-impl-ecore-wl.cpp rename to dali/internal/clipboard/tizen-wayland/ecore-wl/clipboard-impl-ecore-wl.cpp diff --git a/dali/internal/clipboard/tizen-wayland/ecore-wl2/clipboard-impl-ecore-wl2.cpp b/dali/internal/clipboard/tizen-wayland/ecore-wl2/clipboard-impl-ecore-wl2.cpp new file mode 100644 index 0000000..8bcf344 --- /dev/null +++ b/dali/internal/clipboard/tizen-wayland/ecore-wl2/clipboard-impl-ecore-wl2.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2017 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 + +// EXTERNAL INCLUDES +// Ecore is littered with C style cast +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include +#include +#include +#include +#include + +#ifdef DALI_ELDBUS_AVAILABLE +#include +#endif // DALI_ELDBUS_AVAILABLE +#include + +// INTERNAL INCLUDES +#include + +#define CBHM_DBUS_OBJPATH "/org/tizen/cbhm/dbus" +#ifndef CBHM_DBUS_INTERFACE +#define CBHM_DBUS_INTERFACE "org.tizen.cbhm.dbus" +#endif /* CBHM_DBUS_INTERFACE */ +#define CBHM_COUNT_ALL 0 // ATOM_INDEX_CBHM_COUNT_ALL + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Clipboard +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +struct Clipboard::Impl +{ + Impl() + { + Eldbus_Object *eldbus_obj; + cbhm_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION); + eldbus_obj = eldbus_object_get(cbhm_conn, CBHM_DBUS_INTERFACE, CBHM_DBUS_OBJPATH); + eldbus_proxy = eldbus_proxy_get(eldbus_obj, CBHM_DBUS_INTERFACE); + eldbus_name_owner_changed_callback_add(cbhm_conn, CBHM_DBUS_INTERFACE, NULL, cbhm_conn, EINA_TRUE); + eldbus_proxy_signal_handler_add(eldbus_proxy, "ItemClicked", _on_item_clicked, this); + mVisible = false; + mIsFirstTimeHidden = true; + ecore_wl2_display = ecore_wl2_connected_display_get(NULL); + ecore_wl2_input = ecore_wl2_input_default_input_get(ecore_wl2_display); + } + + ~Impl() + { + if (cbhm_conn) + eldbus_connection_unref(cbhm_conn); + } + + Eldbus_Proxy* cbhm_proxy_get() + { + return eldbus_proxy; + } + + Eldbus_Connection* cbhm_connection_get() + { + return cbhm_conn; + } + + void SetItem( const std::string &itemData ) + { + const char *types[10] = {0, }; + int i = -1; + + if (itemData.length() == 0) + { + return; + } + mSendBuffer = itemData; + + // ELM_SEL_TYPE_CLIPBOARD - To distinguish clipboard selection in cbhm + types[++i] = "CLIPBOARD_BEGIN"; + + types[++i] = "text/plain;charset=utf-8"; + + // ELM_SEL_TYPE_CLIPBOARD - To distinguish clipboard selection in cbhm + types[++i] = "CLIPBOARD_END"; + ecore_wl2_dnd_selection_set(ecore_wl2_input, types); + } + + void RequestItem() + { + ecore_wl2_dnd_selection_get(ecore_wl2_input); + } + + char *ExcuteSend( void *event ) + { + Ecore_Wl2_Event_Data_Source_Send *ev = (Ecore_Wl2_Event_Data_Source_Send *)event; + int len_buf = mSendBuffer.length(); + int len_remained = len_buf; + int len_written = 0, ret; + const char *buf = mSendBuffer.c_str(); + + while (len_written < len_buf) + { + ret = write(ev->fd, buf, len_remained); + if (ret == -1) break; + buf += ret; + len_written += ret; + len_remained -= ret; + } + close(ev->fd); + return NULL; + } + + char *ExcuteReceive( void *event ) + { + Ecore_Wl2_Event_Selection_Data_Ready *ev = (Ecore_Wl2_Event_Selection_Data_Ready *)event; + + return (char *)ev->data; + } + + int GetCount() + { + Eldbus_Message *reply, *req; + const char *errname = NULL, *errmsg = NULL; + int count = -1; + + if (!(req = eldbus_proxy_method_call_new(eldbus_proxy, "CbhmGetCount"))) + { + DALI_LOG_ERROR("Failed to create method call on org.freedesktop.DBus.Properties.Get"); + return -1; + } + + eldbus_message_ref(req); + eldbus_message_arguments_append(req, "i", CBHM_COUNT_ALL) ; + reply = eldbus_proxy_send_and_block(eldbus_proxy, req, 100); + if (!reply || eldbus_message_error_get(reply, &errname, &errmsg)) + { + DALI_LOG_ERROR("Unable to call method org.freedesktop.DBus.Properties.Get: %s %s", + errname, errmsg); + eldbus_message_unref(req); + return -1; + } + + if (!eldbus_message_arguments_get(reply, "i", &count)) + { + DALI_LOG_ERROR("Cannot get arguments from eldbus"); + eldbus_message_unref(req); + return -1; + } + + eldbus_message_unref(req); + DALI_LOG_ERROR("cbhm item count(%d)", count); + return count; + } + + void ShowClipboard() + { + eldbus_proxy_call(cbhm_proxy_get(), "CbhmShow", NULL, NULL, -1, "s", "0"); + mIsFirstTimeHidden = true; + mVisible = true; + } + + void HideClipboard( bool skipFirstHide ) + { + if ( skipFirstHide && mIsFirstTimeHidden ) + { + mIsFirstTimeHidden = false; + return; + } + eldbus_proxy_call(cbhm_proxy_get(), "CbhmHide", NULL, NULL, -1, ""); + mIsFirstTimeHidden = false; + mVisible = false; + } + + bool IsVisible() const + { + return mVisible; + } + + static void _on_item_clicked(void *data, const Eldbus_Message *msg EINA_UNUSED) + { + static_cast(data)->RequestItem(); + } + + Eldbus_Proxy *eldbus_proxy; + Eldbus_Connection *cbhm_conn; + + std::string mSendBuffer; + bool mVisible; + bool mIsFirstTimeHidden; + + Ecore_Wl2_Display* ecore_wl2_display; + Ecore_Wl2_Input* ecore_wl2_input; +}; + +Clipboard::Clipboard(Impl* impl) +: mImpl(impl) +{ +} + +Clipboard::~Clipboard() +{ + delete mImpl; +} + +Dali::Clipboard Clipboard::Get() +{ + Dali::Clipboard clipboard; + + Dali::SingletonService service( SingletonService::Get() ); + if ( service ) + { + // Check whether the singleton is already created + Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::Clipboard ) ); + if(handle) + { + // If so, downcast the handle + clipboard = Dali::Clipboard( dynamic_cast< Clipboard* >( handle.GetObjectPtr() ) ); + } + else + { + Clipboard::Impl* impl( new Clipboard::Impl() ); + clipboard = Dali::Clipboard( new Clipboard(impl) ); + service.Register( typeid(Dali::Clipboard), clipboard ); + } + } + + return clipboard; +} + +bool Clipboard::SetItem(const std::string &itemData ) +{ + mImpl->SetItem( itemData ); + return true; +} + +/* + * Request clipboard service to give an item + */ +void Clipboard::RequestItem() +{ + mImpl->RequestItem(); +} + +/* + * Get number of items in clipboard + */ +unsigned int Clipboard::NumberOfItems() +{ + return mImpl->GetCount(); +} + +void Clipboard::ShowClipboard() +{ + mImpl->ShowClipboard(); +} + +void Clipboard::HideClipboard(bool skipFirstHide) +{ + mImpl->HideClipboard(skipFirstHide); +} + +bool Clipboard::IsVisible() const +{ + return mImpl->IsVisible(); +} + +char* Clipboard::ExcuteBuffered( bool type, void *event ) +{ + return (type ? mImpl->ExcuteSend( event ) : mImpl->ExcuteReceive( event )); +} + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali + +#pragma GCC diagnostic pop diff --git a/dali/internal/input/file.list b/dali/internal/input/file.list index 0deb1ef..71ab387 100644 --- a/dali/internal/input/file.list +++ b/dali/internal/input/file.list @@ -16,12 +16,19 @@ adaptor_input_common_src_files=\ ${adaptor_input_dir}/tizen-wayland/ecore-virtual-keyboard.cpp # module: input, backend: tizen-wayland +adaptor_input_tizen_wayland2_src_files=\ + ${adaptor_input_dir}/tizen-wayland/imf-manager-factory-ecore.cpp \ + ${adaptor_input_dir}/tizen-wayland/ecore-wl2/imf-manager-impl-ecore-wl2.cpp \ + ${adaptor_input_dir}/tizen-wayland/ecore-wl2/key-grab-ecore-wl2.cpp \ + ${adaptor_input_dir}/tizen-wayland/key-mapping-ecore.cpp \ + ${adaptor_input_dir}/tizen-wayland/virtual-keyboard-impl-ecore.cpp + adaptor_input_tizen_wayland_src_files=\ - ${adaptor_input_dir}/tizen-wayland/imf-manager-factory-ecore-wl.cpp \ - ${adaptor_input_dir}/tizen-wayland/imf-manager-impl-ecore-wl.cpp \ - ${adaptor_input_dir}/tizen-wayland/key-grab-ecore-wl.cpp \ - ${adaptor_input_dir}/tizen-wayland/key-mapping-ecore-wl.cpp \ - ${adaptor_input_dir}/tizen-wayland/virtual-keyboard-impl-ecore-wl.cpp + ${adaptor_input_dir}/tizen-wayland/imf-manager-factory-ecore.cpp \ + ${adaptor_input_dir}/tizen-wayland/ecore-wl/imf-manager-impl-ecore-wl.cpp \ + ${adaptor_input_dir}/tizen-wayland/ecore-wl/key-grab-ecore-wl.cpp \ + ${adaptor_input_dir}/tizen-wayland/key-mapping-ecore.cpp \ + ${adaptor_input_dir}/tizen-wayland/virtual-keyboard-impl-ecore.cpp # module: input, backend: ubuntu adaptor_input_ubuntu_src_files=\ diff --git a/dali/internal/input/tizen-wayland/imf-manager-impl-ecore-wl.cpp b/dali/internal/input/tizen-wayland/ecore-wl/imf-manager-impl-ecore-wl.cpp similarity index 99% rename from dali/internal/input/tizen-wayland/imf-manager-impl-ecore-wl.cpp rename to dali/internal/input/tizen-wayland/ecore-wl/imf-manager-impl-ecore-wl.cpp index ebe400a..4650178 100644 --- a/dali/internal/input/tizen-wayland/imf-manager-impl-ecore-wl.cpp +++ b/dali/internal/input/tizen-wayland/ecore-wl/imf-manager-impl-ecore-wl.cpp @@ -20,7 +20,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" -#include +#include #include // EXTERNAL INCLUDES @@ -31,7 +31,7 @@ // INTERNAL INCLUDES #include #include -#include +#include #include #include #include diff --git a/dali/internal/input/tizen-wayland/imf-manager-impl-ecore-wl.h b/dali/internal/input/tizen-wayland/ecore-wl/imf-manager-impl-ecore-wl.h similarity index 100% rename from dali/internal/input/tizen-wayland/imf-manager-impl-ecore-wl.h rename to dali/internal/input/tizen-wayland/ecore-wl/imf-manager-impl-ecore-wl.h diff --git a/dali/internal/input/tizen-wayland/key-grab-ecore-wl.cpp b/dali/internal/input/tizen-wayland/ecore-wl/key-grab-ecore-wl.cpp similarity index 100% rename from dali/internal/input/tizen-wayland/key-grab-ecore-wl.cpp rename to dali/internal/input/tizen-wayland/ecore-wl/key-grab-ecore-wl.cpp diff --git a/dali/internal/input/tizen-wayland/ecore-wl2/imf-manager-impl-ecore-wl2.cpp b/dali/internal/input/tizen-wayland/ecore-wl2/imf-manager-impl-ecore-wl2.cpp new file mode 100644 index 0000000..6348e1a --- /dev/null +++ b/dali/internal/input/tizen-wayland/ecore-wl2/imf-manager-impl-ecore-wl2.cpp @@ -0,0 +1,925 @@ +/* + * Copyright (c) 2017 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 +// Ecore is littered with C style cast +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + +#include +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +#define TOKEN_STRING(x) #x + +Ecore_IMF_Input_Panel_Layout panelLayoutMap[] = +{ + ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL, + ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER, + ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL, + ECORE_IMF_INPUT_PANEL_LAYOUT_URL, + ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER, + ECORE_IMF_INPUT_PANEL_LAYOUT_IP, + ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH, + ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY, + ECORE_IMF_INPUT_PANEL_LAYOUT_HEX, + ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL, + ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD, + ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME, + ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON, + ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE +}; + +Ecore_IMF_Autocapital_Type autoCapitalMap[] = +{ + ECORE_IMF_AUTOCAPITAL_TYPE_NONE, + ECORE_IMF_AUTOCAPITAL_TYPE_WORD, + ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE, + ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER, +}; + +Ecore_IMF_Input_Panel_Return_Key_Type returnKeyTypeMap[] = +{ + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT, + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE, + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO, + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN, + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN, + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT, + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH, + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND, + ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN +}; + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +namespace +{ +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_IMF_MANAGER"); +#endif + +// Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead. +size_t Utf8SequenceLength(const unsigned char leadByte) +{ + size_t length = 0; + + if ((leadByte & 0x80) == 0 ) //ASCII character (lead bit zero) + { + length = 1; + } + else if (( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx + { + length = 2; + } + else if (( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx + { + length = 3; + } + else if (( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx + { + length = 4; + } + + return length; +} + +// Static function calls used by ecore 'c' style callback registration +void Commit( void *data, Ecore_IMF_Context *imfContext, void *event_info ) +{ + if ( data ) + { + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); + imfManager->CommitReceived( data, imfContext, event_info ); + } +} + +void PreEdit( void *data, Ecore_IMF_Context *imfContext, void *event_info ) +{ + if ( data ) + { + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); + imfManager->PreEditChanged( data, imfContext, event_info ); + } +} + +Eina_Bool ImfRetrieveSurrounding(void *data, Ecore_IMF_Context *imfContext, char** text, int* cursorPosition ) +{ + if ( data ) + { + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); + return imfManager->RetrieveSurrounding( data, imfContext, text, cursorPosition ); + } + else + { + return false; + } +} + +void InputPanelStateChangeCallback( void* data, Ecore_IMF_Context* context, int value ) +{ + if (!data) + { + return; + } + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); + switch (value) + { + case ECORE_IMF_INPUT_PANEL_STATE_SHOW: + { + imfManager->StatusChangedSignal().Emit( true ); + break; + } + + case ECORE_IMF_INPUT_PANEL_STATE_HIDE: + { + imfManager->StatusChangedSignal().Emit( false ); + break; + } + + case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW: + default: + { + // Do nothing + break; + } + } +} + +void InputPanelLanguageChangeCallback( void* data, Ecore_IMF_Context* context, int value ) +{ + if (!data) + { + return; + } + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); + // Emit the signal that the language has changed + imfManager->LanguageChangedSignal().Emit(value); +} + +void InputPanelGeometryChangedCallback ( void *data, Ecore_IMF_Context *context, int value ) +{ + if (!data) + { + return; + } + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); // Emit signal that the keyboard is resized + // Emit signal that the keyboard is resized + imfManager->ResizedSignal().Emit(value); +} + +void InputPanelKeyboardTypeChangedCallback( void *data, Ecore_IMF_Context *context, int value ) +{ + if( !data ) + { + return; + } + + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); + switch (value) + { + case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE: + { + // Emit Signal that the keyboard type is changed to Software Keyboard + imfManager->KeyboardTypeChangedSignal().Emit( Dali::ImfManager::KeyboardType::SOFTWARE_KEYBOARD ); + break; + } + case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE: + { + // Emit Signal that the keyboard type is changed to Hardware Keyboard + imfManager->KeyboardTypeChangedSignal().Emit( Dali::ImfManager::KeyboardType::HARDWARE_KEYBOARD ); + break; + } + } +} + +/** + * Called when an IMF delete surrounding event is received. + * Here we tell the application that it should delete a certain range. + */ +void ImfDeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *event_info ) +{ + if ( data ) + { + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); + imfManager->DeleteSurrounding( data, imfContext, event_info ); + } +} + +/** + * Called when the input method sends a private command. + */ +void PrivateCommand( void *data, Ecore_IMF_Context *imfContext, void *event_info ) +{ + if ( data ) + { + ImfManagerEcoreWl* imfManager = reinterpret_cast< ImfManagerEcoreWl* > ( data ); + imfManager->SendPrivateCommand( data, imfContext, event_info ); + } +} + +BaseHandle Create() +{ + return ImfManagerEcoreWl::Get(); +} + +TypeRegistration IMF_MANAGER_TYPE( typeid(Dali::ImfManager), typeid(Dali::BaseHandle), Create ); + +} // unnamed namespace + +bool ImfManagerEcoreWl::IsAvailable() +{ + bool available( false ); + + Dali::SingletonService service( SingletonService::Get() ); + if ( service ) + { + available = service.GetSingleton( typeid( Dali::ImfManager ) ); + } + + return available; +} + +Dali::ImfManager ImfManagerEcoreWl::Get() +{ + Dali::ImfManager manager; + + Dali::SingletonService service( SingletonService::Get() ); + if ( service ) + { + // Check whether the singleton is already created + Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::ImfManager ) ); + if( handle ) + { + // If so, downcast the handle + manager = Dali::ImfManager( dynamic_cast< ImfManager* >( handle.GetObjectPtr() ) ); + } + else if ( Adaptor::IsAvailable() ) + { + // Create instance and register singleton only if the adaptor is available + + Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) ); + Any nativeWindow = adaptorImpl.GetNativeWindowHandle(); + + // The Ecore_Wl2_Window needs to use the ImfManager. + // Only when the render surface is window, we can get the Ecore_Wl2_Window. + Ecore_Wl2_Window *ecoreWwin( AnyCast< Ecore_Wl2_Window* >( nativeWindow ) ); + if (ecoreWwin) + { + // If we fail to get Ecore_Wl2_Window, we can't use the ImfManager correctly. + // Thus you have to call "ecore_imf_context_client_window_set" somewhere. + // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent(). + + manager = Dali::ImfManager( new ImfManagerEcoreWl( ecoreWwin ) ); + service.Register( typeid( manager ), manager ); + } + else + { + DALI_LOG_ERROR("Failed to get native window handle\n"); + } + } + } + + return manager; +} + +ImfManagerEcoreWl::ImfManagerEcoreWl( Ecore_Wl2_Window *ecoreWlwin ) +: mIMFContext(), + mIMFCursorPosition( 0 ), + mSurroundingText(), + mRestoreAfterFocusLost( false ), + mIdleCallbackConnected( false ) +{ + ecore_imf_init(); + CreateContext( ecoreWlwin ); + + ConnectCallbacks(); +} + +ImfManagerEcoreWl::~ImfManagerEcoreWl() +{ + DisconnectCallbacks(); + + DeleteContext(); + ecore_imf_shutdown(); +} + +void ImfManagerEcoreWl::CreateContext( Ecore_Wl2_Window *ecoreWlwin ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CreateContext\n" ); + + const char *contextId = ecore_imf_context_default_id_get(); + if( contextId ) + { + mIMFContext = ecore_imf_context_add( contextId ); + + if( mIMFContext ) + { + if( ecoreWlwin ) + { + ecore_imf_context_client_window_set( mIMFContext, + reinterpret_cast( ecore_wl2_window_id_get(ecoreWlwin)) ); + } + } + else + { + DALI_LOG_WARNING("IMF Unable to get IMF Context\n"); + } + } + else + { + DALI_LOG_WARNING("IMF Unable to get IMF Context\n"); + } +} + +void ImfManagerEcoreWl::DeleteContext() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteContext\n" ); + + if ( mIMFContext ) + { + ecore_imf_context_del( mIMFContext ); + mIMFContext = NULL; + } +} + +// Callbacks for predicitive text support. +void ImfManagerEcoreWl::ConnectCallbacks() +{ + if ( mIMFContext ) + { + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::ConnectCallbacks\n" ); + + ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit, this ); + ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit, this ); + ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this ); + ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand, this ); + + ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback, this ); + ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback, this ); + ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback, this ); + ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback, this ); + + ecore_imf_context_retrieve_surrounding_callback_set( mIMFContext, ImfRetrieveSurrounding, this); + } +} + +void ImfManagerEcoreWl::DisconnectCallbacks() +{ + if ( mIMFContext ) + { + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DisconnectCallbacks\n" ); + + ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit ); + ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit ); + ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding ); + ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand ); + + ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback ); + ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback ); + ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback ); + ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback ); + + // We do not need to unset the retrieve surrounding callback. + } +} + +void ImfManagerEcoreWl::Activate() +{ + // Reset mIdleCallbackConnected + mIdleCallbackConnected = false; + + if ( mIMFContext ) + { + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Activate\n" ); + + ecore_imf_context_focus_in( mIMFContext ); + + // emit keyboard activated signal + Dali::ImfManager handle( this ); + mActivatedSignal.Emit( handle ); + } +} + +void ImfManagerEcoreWl::Deactivate() +{ + if( mIMFContext ) + { + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Deactivate\n" ); + + Reset(); + ecore_imf_context_focus_out( mIMFContext ); + } + + // Reset mIdleCallbackConnected + mIdleCallbackConnected = false; +} + +void ImfManagerEcoreWl::Reset() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Reset\n" ); + + if ( mIMFContext ) + { + ecore_imf_context_reset( mIMFContext ); + } +} + +ImfContext* ImfManagerEcoreWl::GetContext() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetContext\n" ); + + return reinterpret_cast(mIMFContext); +} + +bool ImfManagerEcoreWl::RestoreAfterFocusLost() const +{ + return mRestoreAfterFocusLost; +} + +void ImfManagerEcoreWl::SetRestoreAfterFocusLost( bool toggle ) +{ + mRestoreAfterFocusLost = toggle; +} + +/** + * Called when an IMF Pre-Edit changed event is received. + * We are still predicting what the user is typing. The latest string is what the IMF module thinks + * the user wants to type. + */ +void ImfManagerEcoreWl::PreEditChanged( void*, Ecore_IMF_Context* imfContext, void* event_info ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::PreEditChanged\n" ); + + char* preEditString( NULL ); + int cursorPosition( 0 ); + Eina_List* attrs = NULL; + Eina_List* l = NULL; + + Ecore_IMF_Preedit_Attr* attr; + + // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string. + // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string. + ecore_imf_context_preedit_string_with_attributes_get( imfContext, &preEditString, &attrs, &cursorPosition ); + + if ( attrs ) + { + // iterate through the list of attributes getting the type, start and end position. + for ( l = attrs, (attr = static_cast( eina_list_data_get(l) ) ); l; l = eina_list_next(l), ( attr = static_cast( eina_list_data_get(l) ) )) + { +#ifdef DALI_PROFILE_UBUNTU + if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3 ) // (Ecore_IMF) +#else // DALI_PROFILE_UBUNTU + if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB4 ) // (Ecore_IMF) +#endif // DALI_PROFILE_UBUNTU + { + // check first byte so know how many bytes a character is represented by as keyboard returns cursor position in bytes. Which is different for some languages. + + size_t visualCharacterIndex = 0; + size_t byteIndex = 0; + + // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ). + const char leadByte = preEditString[byteIndex]; + while( leadByte != '\0' ) + { + // attr->end_index is provided as a byte position not character and we need to know the character position. + const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character. + if ( byteIndex == attr->end_index ) + { + cursorPosition = visualCharacterIndex; + break; + // end loop as found cursor position that matches byte position + } + else + { + byteIndex += currentSequenceLength; // jump to next character + visualCharacterIndex++; // increment character count so we know our position for when we get a match + } + + DALI_ASSERT_DEBUG( visualCharacterIndex < strlen( preEditString )); + } + } + } + } + + if ( Dali::Adaptor::IsAvailable() ) + { + Dali::ImfManager handle( this ); + Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::PREEDIT, preEditString, cursorPosition, 0 ); + Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData ); + + if ( callbackData.update ) + { + SetCursorPosition( callbackData.cursorPosition ); + SetSurroundingText( callbackData.currentText ); + + NotifyCursorPosition(); + } + + if ( callbackData.preeditResetRequired ) + { + Reset(); + } + } + free( preEditString ); +} + +void ImfManagerEcoreWl::CommitReceived( void*, Ecore_IMF_Context* imfContext, void* event_info ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CommitReceived\n" ); + + if ( Dali::Adaptor::IsAvailable() ) + { + const std::string keyString( static_cast( event_info ) ); + + Dali::ImfManager handle( this ); + Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::COMMIT, keyString, 0, 0 ); + Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData ); + + if( callbackData.update ) + { + SetCursorPosition( callbackData.cursorPosition ); + SetSurroundingText( callbackData.currentText ); + + NotifyCursorPosition(); + } + } +} + +/** + * Called when an IMF retrieve surround event is received. + * Here the IMF module wishes to know the string we are working with and where within the string the cursor is + * We need to signal the application to tell us this information. + */ +Eina_Bool ImfManagerEcoreWl::RetrieveSurrounding( void* data, Ecore_IMF_Context* imfContext, char** text, int* cursorPosition ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::RetrieveSurrounding\n" ); + + Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::GETSURROUNDING, std::string(), 0, 0 ); + Dali::ImfManager handle( this ); + Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfData ); + + if( callbackData.update ) + { + if( text ) + { + // The memory allocated by strdup() can be freed by ecore_imf_context_surrounding_get() internally. + *text = strdup( callbackData.currentText.c_str() ); + } + + if( cursorPosition ) + { + mIMFCursorPosition = static_cast( callbackData.cursorPosition ); + *cursorPosition = mIMFCursorPosition; + } + } + + return EINA_TRUE; +} + +/** + * Called when an IMF delete surrounding event is received. + * Here we tell the application that it should delete a certain range. + */ +void ImfManagerEcoreWl::DeleteSurrounding( void* data, Ecore_IMF_Context* imfContext, void* event_info ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteSurrounding\n" ); + + if( Dali::Adaptor::IsAvailable() ) + { + Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast( event_info ); + + Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::DELETESURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars ); + Dali::ImfManager handle( this ); + mEventSignal.Emit( handle, imfData ); + } +} + +/** + * Called when the input method sends a private command. + */ +void ImfManagerEcoreWl::SendPrivateCommand( void* data, Ecore_IMF_Context* imfContext, void* event_info ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SendPrivateCommand\n" ); + + if( Dali::Adaptor::IsAvailable() ) + { + const char* privateCommandSendEvent = static_cast( event_info ); + + Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::PRIVATECOMMAND, privateCommandSendEvent, 0, 0 ); + Dali::ImfManager handle( this ); + mEventSignal.Emit( handle, imfData ); + } +} + +void ImfManagerEcoreWl::NotifyCursorPosition() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::NotifyCursorPosition\n" ); + + if( mIMFContext ) + { + ecore_imf_context_cursor_position_set( mIMFContext, mIMFCursorPosition ); + } +} + +void ImfManagerEcoreWl::SetCursorPosition( unsigned int cursorPosition ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetCursorPosition\n" ); + + mIMFCursorPosition = static_cast( cursorPosition ); +} + +unsigned int ImfManagerEcoreWl::GetCursorPosition() const +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetCursorPosition\n" ); + + return static_cast( mIMFCursorPosition ); +} + +void ImfManagerEcoreWl::SetSurroundingText( const std::string& text ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetSurroundingText\n" ); + + mSurroundingText = text; +} + +const std::string& ImfManagerEcoreWl::GetSurroundingText() const +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetSurroundingText\n" ); + + return mSurroundingText; +} + +void ImfManagerEcoreWl::NotifyTextInputMultiLine( bool multiLine ) +{ + Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext); + ecore_imf_context_input_hint_set( mIMFContext, + static_cast< Ecore_IMF_Input_Hints >( multiLine ? + (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) : + (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE))); +} + +Dali::ImfManager::TextDirection ImfManagerEcoreWl::GetTextDirection() +{ + Dali::ImfManager::TextDirection direction ( Dali::ImfManager::LeftToRight ); + + if ( ImfManager::IsAvailable() /* We do not want to create an instance of ImfManager */ ) + { + if ( mIMFContext ) + { + char* locale( NULL ); + ecore_imf_context_input_panel_language_locale_get( mIMFContext, &locale ); + + if ( locale ) + { + direction = static_cast< Dali::ImfManager::TextDirection >( Locale::GetDirection( std::string( locale ) ) ); + free( locale ); + } + } + } + return direction; +} + +Rect ImfManagerEcoreWl::GetInputMethodArea() +{ + int xPos, yPos, width, height; + + width = height = xPos = yPos = 0; + + if( mIMFContext ) + { + ecore_imf_context_input_panel_geometry_get( mIMFContext, &xPos, &yPos, &width, &height ); + } + else + { + DALI_LOG_WARNING("VKB Unable to get IMF Context so GetSize unavailable\n"); + // return 0 as real size unknown. + } + + return Rect(xPos,yPos,width,height); +} + +void ImfManagerEcoreWl::ApplyOptions( const InputMethodOptions& options ) +{ + using namespace Dali::InputMethod::Category; + + int index; + + if (mIMFContext == NULL) + { + DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n"); + return; + } + + if ( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) ) + { + ecore_imf_context_input_panel_layout_set( mIMFContext, panelLayoutMap[index] ); + } + if ( mOptions.CompareAndSet(AUTO_CAPITALISE, options, index) ) + { + ecore_imf_context_autocapital_type_set( mIMFContext, autoCapitalMap[index] ); + } + if ( mOptions.CompareAndSet(ACTION_BUTTON_TITLE, options, index) ) + { + ecore_imf_context_input_panel_return_key_type_set( mIMFContext, returnKeyTypeMap[index] ); + } + if ( mOptions.CompareAndSet(VARIATION, options, index) ) + { + ecore_imf_context_input_panel_layout_variation_set( mIMFContext, index ); + } +} + +void ImfManagerEcoreWl::SetInputPanelData( const std::string& data ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetInputPanelData\n" ); + + if( mIMFContext ) + { + int length = data.length(); + ecore_imf_context_input_panel_imdata_set( mIMFContext, data.c_str(), length ); + } +} + +void ImfManagerEcoreWl::GetInputPanelData( std::string& data ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelData\n" ); + + if( mIMFContext ) + { + int length = 4096; // The max length is 4096 bytes + Dali::Vector< char > buffer; + buffer.Resize( length ); + ecore_imf_context_input_panel_imdata_get( mIMFContext, &buffer[0], &length ); + data = std::string( buffer.Begin(), buffer.End() ); + } +} + +Dali::ImfManager::State ImfManagerEcoreWl::GetInputPanelState() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelState\n" ); + + if( mIMFContext ) + { + int value; + value = ecore_imf_context_input_panel_state_get( mIMFContext ); + + switch (value) + { + case ECORE_IMF_INPUT_PANEL_STATE_SHOW: + { + return Dali::ImfManager::SHOW; + break; + } + + case ECORE_IMF_INPUT_PANEL_STATE_HIDE: + { + return Dali::ImfManager::HIDE; + break; + } + + case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW: + { + return Dali::ImfManager::WILL_SHOW; + break; + } + + default: + { + return Dali::ImfManager::DEFAULT; + } + } + } + return Dali::ImfManager::DEFAULT; +} + +void ImfManagerEcoreWl::SetReturnKeyState( bool visible ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetReturnKeyState\n" ); + + if( mIMFContext ) + { + ecore_imf_context_input_panel_return_key_disabled_set( mIMFContext, !visible ); + } +} + +void ImfManagerEcoreWl::AutoEnableInputPanel( bool enabled ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::AutoEnableInputPanel\n" ); + + if( mIMFContext ) + { + ecore_imf_context_input_panel_enabled_set( mIMFContext, enabled ); + } +} + +void ImfManagerEcoreWl::ShowInputPanel() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::ShowInputPanel\n" ); + + if( mIMFContext ) + { + ecore_imf_context_input_panel_show( mIMFContext ); + } +} + +void ImfManagerEcoreWl::HideInputPanel() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::HideInputPanel\n" ); + + if( mIMFContext ) + { + ecore_imf_context_input_panel_hide( mIMFContext ); + } +} + +Dali::ImfManager::KeyboardType ImfManagerEcoreWl::GetKeyboardType() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetKeyboardType\n" ); + +#ifdef OVER_TIZEN_VERSION_4 + if( mIMFContext ) + { + int value; + value = ecore_imf_context_keyboard_mode_get( mIMFContext ); + + switch (value) + { + case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE: + { + return Dali::ImfManager::SOFTWARE_KEYBOARD; + break; + } + case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE: + { + return Dali::ImfManager::HARDWARE_KEYBOARD; + break; + } + } + } +#endif // OVER_TIZEN_VERSION_4 + return Dali::ImfManager::KeyboardType::SOFTWARE_KEYBOARD; +} + +std::string ImfManagerEcoreWl::GetInputPanelLocale() +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelLocale\n" ); + + std::string locale = ""; + + if( mIMFContext ) + { + char* value = NULL; + ecore_imf_context_input_panel_language_locale_get( mIMFContext, &value ); + + if( value ) + { + std::string valueCopy( value ); + locale = valueCopy; + + // The locale string retrieved must be freed with free(). + free( value ); + } + } + return locale; +} + +} // Adaptor + +} // Internal + +} // Dali + +#pragma GCC diagnostic pop \ No newline at end of file diff --git a/dali/internal/input/tizen-wayland/ecore-wl2/imf-manager-impl-ecore-wl2.h b/dali/internal/input/tizen-wayland/ecore-wl2/imf-manager-impl-ecore-wl2.h new file mode 100644 index 0000000..700bd9a --- /dev/null +++ b/dali/internal/input/tizen-wayland/ecore-wl2/imf-manager-impl-ecore-wl2.h @@ -0,0 +1,267 @@ +#ifndef DALI_INTERNAL_INPUT_COMMON_IMF_MANAGER_IMPL_ECORE_WL2_H +#define DALI_INTERNAL_INPUT_COMMON_IMF_MANAGER_IMPL_ECORE_WL2_H + +/* + * Copyright (c) 2018 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 +//TIZEN_MIGRATION +#include +// + + +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +class RenderSurface; + +namespace Internal +{ + +namespace Adaptor +{ + +class ImfManagerEcoreWl : public Dali::Internal::Adaptor::ImfManager +{ +public: + + /** + * Check whether the ImfManager is available. + * @return true if available, false otherwise + */ + static bool IsAvailable(); + + /** + * Get the IMF manager instance, it creates the instance if it has not already been created. + * Internally, a check should be made using IsAvailable() before this is called as we do not want + * to create an instance if not needed by applications. + * @see IsAvailable() + */ + static Dali::ImfManager Get(); + + /** + * Connect Callbacks required for IMF. + * If you don't connect imf callbacks, you can't get the key events. + * The events are PreeditChanged, Commit, DeleteSurrounding and PrivateCommand. + */ + void ConnectCallbacks() override; + + /** + * Disconnect Callbacks attached to imf context. + */ + void DisconnectCallbacks() override; + + /** + * @copydoc Dali::ImfManager::Activate() + */ + void Activate() override; + + /** + * @copydoc Dali::ImfManager::Deactivate() + */ + void Deactivate() override; + + /** + * @copydoc Dali::ImfManager::Reset() + */ + void Reset() override; + + /** + * @copydoc Dali::ImfManager::GetContext() + */ + ImfContext* GetContext() override; + + /** + * @copydoc Dali::ImfManager::RestoreAfterFocusLost() + */ + bool RestoreAfterFocusLost() const override; + + /** + * @copydoc Dali::ImfManager::SetRestoreAfterFocusLost() + */ + void SetRestoreAfterFocusLost( bool toggle ) override; + + /** + * @copydoc Dali::ImfManager::PreEditChanged() + */ + void PreEditChanged( void *data, Ecore_IMF_Context *imfContext, void *event_info ); + + /** + * @copydoc Dali::ImfManager::NotifyCursorPosition() + */ + void CommitReceived( void *data, Ecore_IMF_Context *imfContext, void *event_info ); + + /** + * @copydoc Dali::ImfManager::NotifyCursorPosition() + */ + Eina_Bool RetrieveSurrounding( void *data, Ecore_IMF_Context *imfContext, char** text, int* cursorPosition ); + + /** + * @copydoc Dali::ImfManager::DeleteSurrounding() + */ + void DeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *event_info ); + + /** + * @copydoc Dali::ImfManager::SendPrivateCommand() + */ + void SendPrivateCommand( void* data, Ecore_IMF_Context* imfContext, void* event_info ); + + // Cursor related + /** + * @copydoc Dali::ImfManager::NotifyCursorPosition() + */ + void NotifyCursorPosition() override; + + /** + * @copydoc Dali::ImfManager::SetCursorPosition() + */ + void SetCursorPosition( unsigned int cursorPosition ) override; + + /** + * @copydoc Dali::ImfManager::GetCursorPosition() + */ + unsigned int GetCursorPosition() const override; + + /** + * @copydoc Dali::ImfManager::SetSurroundingText() + */ + void SetSurroundingText( const std::string& text ) override; + + /** + * @copydoc Dali::ImfManager::GetSurroundingText() + */ + const std::string& GetSurroundingText() const override; + + /** + * @copydoc Dali::ImfManager::NotifyTextInputMultiLine() + */ + void NotifyTextInputMultiLine( bool multiLine ) override; + + /** + * @copydoc Dali::ImfManager::GetTextDirection() + */ + Dali::ImfManager::TextDirection GetTextDirection() override; + + /** + * @copydoc Dali::ImfManager::GetInputMethodArea() + */ + Dali::Rect GetInputMethodArea() override; + + /** + * @copydoc Dali::ImfManager::ApplyOptions() + */ + void ApplyOptions( const InputMethodOptions& options ) override; + + /** + * @copydoc Dali::ImfManager::SetInputPanelData() + */ + void SetInputPanelData( const std::string& data ) override; + + /** + * @copydoc Dali::ImfManager::GetInputPanelData() + */ + void GetInputPanelData( std::string& data ) override; + + /** + * @copydoc Dali::ImfManager::GetInputPanelState() + */ + Dali::ImfManager::State GetInputPanelState() override; + + /** + * @copydoc Dali::ImfManager::SetReturnKeyState() + */ + void SetReturnKeyState( bool visible ) override; + + /** + * @copydoc Dali::ImfManager::AutoEnableInputPanel() + */ + void AutoEnableInputPanel( bool enabled ) override; + + /** + * @copydoc Dali::ImfManager::ShowInputPanel() + */ + void ShowInputPanel() override; + + /** + * @copydoc Dali::ImfManager::HideInputPanel() + */ + void HideInputPanel() override; + + /** + * @copydoc Dali::ImfManager::GetKeyboardType() + */ + Dali::ImfManager::KeyboardType GetKeyboardType() override; + + /** + * @copydoc Dali::ImfManager::GetInputPanelLocale() + */ + std::string GetInputPanelLocale() override; + +protected: + + /** + * Destructor. + */ + virtual ~ImfManagerEcoreWl() override; + +private: + /** + * Context created the first time and kept until deleted. + * @param[in] ecoreWlwin, The window is created by application. + */ + void CreateContext( Ecore_Wl2_Window *ecoreWlwin ); + + /** + * @copydoc Dali::ImfManager::DeleteContext() + */ + void DeleteContext(); + +private: + // Undefined + explicit ImfManagerEcoreWl( Ecore_Wl2_Window *ecoreWlwin ); + explicit ImfManagerEcoreWl( const ImfManager& ) = delete; + ImfManagerEcoreWl& operator=( ImfManager& ) = delete; + +private: + Ecore_IMF_Context* mIMFContext; + int mIMFCursorPosition; + std::string mSurroundingText; + + bool mRestoreAfterFocusLost:1; ///< Whether the keyboard needs to be restored (activated ) after focus regained. + bool mIdleCallbackConnected:1; ///< Whether the idle callback is already connected. + + std::vector mKeyEvents; ///< Stores key events to be sent from idle call-back. + InputMethodOptions mOptions; +}; + + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali + +#endif // DALI_INTERNAL_INPUT_COMMON_IMF_MANAGER_IMPL_ECORE_WL2_H diff --git a/dali/internal/input/tizen-wayland/ecore-wl2/key-grab-ecore-wl2.cpp b/dali/internal/input/tizen-wayland/ecore-wl2/key-grab-ecore-wl2.cpp new file mode 100644 index 0000000..1559039 --- /dev/null +++ b/dali/internal/input/tizen-wayland/ecore-wl2/key-grab-ecore-wl2.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2016 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 + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include + +#include +#include + +using namespace std; + +namespace Dali +{ + +namespace KeyGrab +{ + +bool GrabKeyTopmost( Window window, Dali::KEY daliKey ) +{ + return GrabKey( window, daliKey, TOPMOST); +} + + +bool UngrabKeyTopmost( Window window, Dali::KEY daliKey ) +{ + return UngrabKey( window, daliKey ); +} + + +bool GrabKey( Window window, Dali::KEY daliKey, KeyGrabMode grabMode ) +{ + Ecore_Wl2_Window_Keygrab_Mode wlGrabMode; + if( grabMode == TOPMOST ) + { + wlGrabMode = ECORE_WL2_WINDOW_KEYGRAB_TOPMOST; + } + else if( grabMode == SHARED ) + { + wlGrabMode = ECORE_WL2_WINDOW_KEYGRAB_SHARED; + } + else if( grabMode == OVERRIDE_EXCLUSIVE ) + { + wlGrabMode = ECORE_WL2_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE; + } + else if( grabMode == EXCLUSIVE ) + { + wlGrabMode = ECORE_WL2_WINDOW_KEYGRAB_EXCLUSIVE; + } + else + { + return false; + } + + return ecore_wl2_window_keygrab_set( AnyCast( window.GetNativeHandle() ), + Dali::Internal::Adaptor::KeyLookup::GetKeyName( daliKey ), + 0, 0, 0, wlGrabMode ); +} + + +bool UngrabKey( Window window, Dali::KEY daliKey ) +{ + return ecore_wl2_window_keygrab_unset( AnyCast( window.GetNativeHandle() ), + Dali::Internal::Adaptor::KeyLookup::GetKeyName( daliKey ), + 0, 0 ); +} + + +bool GrabKeyList( Window window, const Dali::Vector& daliKeyVector, const Dali::Vector& grabModeVector, Dali::Vector& returnVector) +{ + const Dali::Vector::SizeType returnCount = returnVector.Count(); + const Dali::Vector::SizeType keyCount = daliKeyVector.Count(); + const Dali::Vector::SizeType keyGrabModeCount = grabModeVector.Count(); + + if( keyCount != keyGrabModeCount || keyCount != returnCount || keyCount == 0 ) + { + return false; + } + + eina_init(); + + Eina_List* keyList = NULL; + { + for( Dali::Vector::SizeType index = 0; index < keyCount; ++index ) + { + Ecore_Wl2_Window_Keygrab_Info info; + info.key = const_cast(Dali::Internal::Adaptor::KeyLookup::GetKeyName( daliKeyVector[index] )); + + switch( grabModeVector[index] ) + { + case TOPMOST: + { + info.mode = ECORE_WL2_WINDOW_KEYGRAB_TOPMOST; + break; + } + case SHARED: + { + info.mode = ECORE_WL2_WINDOW_KEYGRAB_SHARED; + break; + } + case OVERRIDE_EXCLUSIVE: + { + info.mode = ECORE_WL2_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE; + break; + } + case EXCLUSIVE: + { + info.mode = ECORE_WL2_WINDOW_KEYGRAB_EXCLUSIVE; + break; + } + default: + { + info.mode = ECORE_WL2_WINDOW_KEYGRAB_UNKNOWN; + break; + } + } + + keyList = eina_list_append( keyList, &info ); + } + } + + Eina_List* grabList = ecore_wl2_window_keygrab_list_set( AnyCast( window.GetNativeHandle() ), keyList ); + + returnVector.Resize( keyCount, true ); + + Eina_List* l = NULL; + Eina_List* m = NULL; + void *listData = NULL; + void *data = NULL; + if( grabList != NULL ) + { + EINA_LIST_FOREACH( grabList, m, data ) + { + Dali::Vector::SizeType index = 0; + EINA_LIST_FOREACH( keyList, l, listData ) + { + if((static_cast(listData))->key == NULL) + { + DALI_LOG_ERROR("input key list has null data!"); + break; + } + + if( strcmp( static_cast(data), static_cast(listData)->key ) == 0 ) + { + returnVector[index] = false; + } + ++index; + } + } + } + + eina_list_free( keyList ); + eina_list_free( grabList ); + eina_shutdown(); + + return true; +} + +bool UngrabKeyList( Window window, const Dali::Vector& daliKeyVector, Dali::Vector& returnVector) +{ + const Dali::Vector::SizeType returnCount = returnVector.Count(); + const Dali::Vector::SizeType keyCount = daliKeyVector.Count(); + + if( keyCount != returnCount ||keyCount == 0 ) + { + return false; + } + + eina_init(); + + Eina_List* keyList = NULL; + { + for( Dali::Vector::SizeType index = 0; index < keyCount; ++index ) + { + Ecore_Wl2_Window_Keygrab_Info info; + info.key = const_cast(Dali::Internal::Adaptor::KeyLookup::GetKeyName( daliKeyVector[index] )); + keyList = eina_list_append( keyList, &info ); + } + } + + Eina_List* ungrabList = ecore_wl2_window_keygrab_list_unset( AnyCast( window.GetNativeHandle() ), keyList ); + + returnVector.Resize( keyCount, true ); + + Eina_List* l = NULL; + Eina_List* m = NULL; + void *listData = NULL; + void *data = NULL; + + if( ungrabList != NULL ) + { + EINA_LIST_FOREACH( ungrabList, m, data ) + { + Dali::Vector::SizeType index = 0; + EINA_LIST_FOREACH( keyList, l, listData ) + { + if( strcmp( static_cast(data), static_cast(listData)->key ) == 0 ) + { + returnVector[index] = false; + } + ++index; + } + } + } + + eina_list_free( keyList ); + eina_list_free( ungrabList ); + eina_shutdown(); + + return true; +} + +} // namespace KeyGrab + +} // namespace Dali + diff --git a/dali/internal/input/tizen-wayland/imf-manager-factory-ecore-wl.cpp b/dali/internal/input/tizen-wayland/imf-manager-factory-ecore.cpp similarity index 84% rename from dali/internal/input/tizen-wayland/imf-manager-factory-ecore-wl.cpp rename to dali/internal/input/tizen-wayland/imf-manager-factory-ecore.cpp index 76a2459..4a5ee91 100644 --- a/dali/internal/input/tizen-wayland/imf-manager-factory-ecore-wl.cpp +++ b/dali/internal/input/tizen-wayland/imf-manager-factory-ecore.cpp @@ -16,7 +16,11 @@ */ #include -#include +#ifdef ECORE_WL2 +#include +#else +#include +#endif namespace Dali { diff --git a/dali/internal/input/tizen-wayland/key-mapping-ecore-wl.cpp b/dali/internal/input/tizen-wayland/key-mapping-ecore.cpp similarity index 100% rename from dali/internal/input/tizen-wayland/key-mapping-ecore-wl.cpp rename to dali/internal/input/tizen-wayland/key-mapping-ecore.cpp diff --git a/dali/internal/input/tizen-wayland/virtual-keyboard-impl-ecore-wl.cpp b/dali/internal/input/tizen-wayland/virtual-keyboard-impl-ecore.cpp similarity index 99% rename from dali/internal/input/tizen-wayland/virtual-keyboard-impl-ecore-wl.cpp rename to dali/internal/input/tizen-wayland/virtual-keyboard-impl-ecore.cpp index 4ba175d..96ac0a2 100644 --- a/dali/internal/input/tizen-wayland/virtual-keyboard-impl-ecore-wl.cpp +++ b/dali/internal/input/tizen-wayland/virtual-keyboard-impl-ecore.cpp @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include #include #include diff --git a/dali/internal/system/tizen/widget-application-impl-tizen.cpp b/dali/internal/system/tizen/widget-application-impl-tizen.cpp index 9464f42..c40a872 100644 --- a/dali/internal/system/tizen/widget-application-impl-tizen.cpp +++ b/dali/internal/system/tizen/widget-application-impl-tizen.cpp @@ -51,7 +51,11 @@ int OnInstanceInit(widget_base_instance_h instanceHandle, bundle *content, int w Dali::Window window = application->GetWindow(); window.ShowIndicator(Dali::Window::INVISIBLE); Any nativeHandle = window.GetNativeHandle(); +#ifdef ECORE_WL2 + Ecore_Wl2_Window * wlWindow = AnyCast( nativeHandle ); +#else Ecore_Wl_Window * wlWindow = AnyCast( nativeHandle ); +#endif widget_base_context_window_bind( instanceHandle, id, wlWindow ); window.SetSize( Dali::Window::WindowSize( w, h ) ); diff --git a/dali/internal/window-system/common/display-connection-factory.h b/dali/internal/window-system/common/display-connection-factory.h index 14f5bd0..2cf9b6a 100644 --- a/dali/internal/window-system/common/display-connection-factory.h +++ b/dali/internal/window-system/common/display-connection-factory.h @@ -19,6 +19,7 @@ */ #include +#include namespace Dali { @@ -43,6 +44,8 @@ extern std::unique_ptr GetDisplayConnectionFactory(); extern void DisplayConnectionFactoryGetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical); +extern void DisplayConnectionFactoryGetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical); + } // namespace Adaptor } // namespace Internal diff --git a/dali/internal/window-system/common/display-connection-impl.cpp b/dali/internal/window-system/common/display-connection-impl.cpp index 0ba1872..4e82f41 100644 --- a/dali/internal/window-system/common/display-connection-impl.cpp +++ b/dali/internal/window-system/common/display-connection-impl.cpp @@ -32,6 +32,11 @@ void DisplayConnection::GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVer DisplayConnectionFactoryGetDpi( dpiHorizontal, dpiVertical ); } +void DisplayConnection::GetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical) +{ + DisplayConnectionFactoryGetDpi( nativeWindow, dpiHorizontal, dpiVertical ); +} + } // namespace Adaptor } // namespace internal diff --git a/dali/internal/window-system/common/display-connection-impl.h b/dali/internal/window-system/common/display-connection-impl.h index cd94d76..4383f7e 100644 --- a/dali/internal/window-system/common/display-connection-impl.h +++ b/dali/internal/window-system/common/display-connection-impl.h @@ -68,6 +68,11 @@ public: static void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical); /** + * @copydoc Dali::DisplayConnection::GetDpi with native window + */ + static void GetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical); + + /** * @copydoc Dali::DisplayConnection::ConsumeEvents */ virtual void ConsumeEvents() = 0; diff --git a/dali/internal/window-system/common/display-connection.cpp b/dali/internal/window-system/common/display-connection.cpp index 0a28469..7d56e2a 100644 --- a/dali/internal/window-system/common/display-connection.cpp +++ b/dali/internal/window-system/common/display-connection.cpp @@ -69,6 +69,11 @@ void DisplayConnection::GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVer Internal::Adaptor::DisplayConnection::GetDpi(dpiHorizontal, dpiVertical); } +void DisplayConnection::GetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical) +{ + Internal::Adaptor::DisplayConnection::GetDpi(nativeWindow, dpiHorizontal, dpiVertical); +} + void DisplayConnection::ConsumeEvents() { mImpl->ConsumeEvents(); diff --git a/dali/internal/window-system/common/display-connection.h b/dali/internal/window-system/common/display-connection.h index 9a9243c..2bf4417 100644 --- a/dali/internal/window-system/common/display-connection.h +++ b/dali/internal/window-system/common/display-connection.h @@ -23,6 +23,7 @@ // INTERNAL INCLUDES #include +#include #include @@ -88,6 +89,14 @@ public: static void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical); /** + * @brief Get DPI + * @param [in] handle A pointer to a newly allocated DisplayConnection resource + * @param[out] dpiHorizontal set to the horizontal dpi + * @param[out] dpiVertical set to the vertical dpi + */ + static void GetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical); + + /** * @brief Consumes any possible events on the queue so that there is no leaking between frames */ void ConsumeEvents(); diff --git a/dali/internal/window-system/common/ecore-indicator-impl.cpp b/dali/internal/window-system/common/ecore-indicator-impl.cpp index 3c9a6b1..b097c48 100644 --- a/dali/internal/window-system/common/ecore-indicator-impl.cpp +++ b/dali/internal/window-system/common/ecore-indicator-impl.cpp @@ -24,11 +24,15 @@ #pragma GCC diagnostic ignored "-Wold-style-cast" #include #include -#ifdef WAYLAND +#ifdef WAYLAND // WAYLAND +#ifdef ECORE_WL2 //ECORE_WL2 +#include +#else //ECORE_WL2 #include -#else +#endif //ECORE_WL2 +#else // WAYLAND #include -#endif +#endif // WAYLAND #include #include @@ -369,7 +373,11 @@ struct Indicator::Impl { #if defined(DALI_PROFILE_MOBILE) #if defined(WAYLAND) +#if defined(ECORE_WL2) + mEcoreEventHandler = ecore_event_handler_add(ECORE_WL2_EVENT_INDICATOR_FLICK, EcoreEventIndicator, this); +#else mEcoreEventHandler = ecore_event_handler_add(ECORE_WL_EVENT_INDICATOR_FLICK, EcoreEventIndicator, this); +#endif #else mEcoreEventHandler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, EcoreEventClientMessage, this); #endif diff --git a/dali/internal/window-system/file.list b/dali/internal/window-system/file.list index d272ee9..a871f8e 100644 --- a/dali/internal/window-system/file.list +++ b/dali/internal/window-system/file.list @@ -19,13 +19,22 @@ adaptor_window_system_tizen_mobile_src_files=\ # module: window-system, backend: tizen-wayland adaptor_window_system_tizen_wayland_src_files=\ - ${adaptor_window_system_dir}/tizen-wayland/display-connection-factory-ecore-wl.cpp \ - ${adaptor_window_system_dir}/tizen-wayland/display-connection-impl-ecore-wl.cpp \ - ${adaptor_window_system_dir}/tizen-wayland/event-handler-ecore-wl.cpp \ - ${adaptor_window_system_dir}/tizen-wayland/pixmap-render-surface-ecore-wl.cpp \ - ${adaptor_window_system_dir}/tizen-wayland/render-surface-ecore-wl.cpp \ - ${adaptor_window_system_dir}/tizen-wayland/window-impl-ecore-wl.cpp \ - ${adaptor_window_system_dir}/tizen-wayland/window-render-surface-ecore-wl.cpp + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl/display-connection-factory-ecore-wl.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl/display-connection-impl-ecore-wl.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl/event-handler-ecore-wl.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl/pixmap-render-surface-ecore-wl.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl/render-surface-ecore-wl.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl/window-impl-ecore-wl.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl/window-render-surface-ecore-wl.cpp + +adaptor_window_system_tizen_wayland2_src_files=\ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl2/display-connection-factory-ecore-wl2.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl2/display-connection-impl-ecore-wl2.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl2/event-handler-ecore-wl2.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl2/pixmap-render-surface-ecore-wl2.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl2/render-surface-ecore-wl2.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl2/window-impl-ecore-wl2.cpp \ + ${adaptor_window_system_dir}/tizen-wayland/ecore-wl2/window-render-surface-ecore-wl2.cpp # module: window-system, backend: tizen-wearable adaptor_window_system_tizen_wearable_src_files=\ diff --git a/dali/internal/window-system/tizen-wayland/display-connection-impl-wl.h b/dali/internal/window-system/tizen-wayland/display-connection-impl-wl.h index 9b2202f..153d8f2 100644 --- a/dali/internal/window-system/tizen-wayland/display-connection-impl-wl.h +++ b/dali/internal/window-system/tizen-wayland/display-connection-impl-wl.h @@ -71,6 +71,11 @@ public: static void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical); /** + * @copydoc Dali::DisplayConnection::GetDpi with native window + */ + static void GetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical); + + /** * @copydoc Dali::DisplayConnection::ConsumeEvents */ void ConsumeEvents(); diff --git a/dali/internal/window-system/tizen-wayland/display-connection-factory-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-factory-ecore-wl.cpp similarity index 86% rename from dali/internal/window-system/tizen-wayland/display-connection-factory-ecore-wl.cpp rename to dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-factory-ecore-wl.cpp index e3fd4d0..5687ad7 100644 --- a/dali/internal/window-system/tizen-wayland/display-connection-factory-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-factory-ecore-wl.cpp @@ -15,8 +15,8 @@ * */ -#include -#include +#include +#include namespace Dali { @@ -46,4 +46,4 @@ void DisplayConnectionFactoryGetDpi(unsigned int& dpiHorizontal, unsigned int& d } } -} \ No newline at end of file +} diff --git a/dali/internal/window-system/tizen-wayland/display-connection-factory-ecore-wl.h b/dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-factory-ecore-wl.h similarity index 100% rename from dali/internal/window-system/tizen-wayland/display-connection-factory-ecore-wl.h rename to dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-factory-ecore-wl.h diff --git a/dali/internal/window-system/tizen-wayland/display-connection-impl-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-impl-ecore-wl.cpp similarity index 96% rename from dali/internal/window-system/tizen-wayland/display-connection-impl-ecore-wl.cpp rename to dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-impl-ecore-wl.cpp index 42ffab6..c43e5a5 100644 --- a/dali/internal/window-system/tizen-wayland/display-connection-impl-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-impl-ecore-wl.cpp @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include +#include // EXTERNAL_HEADERS #include diff --git a/dali/internal/window-system/tizen-wayland/display-connection-impl-ecore-wl.h b/dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-impl-ecore-wl.h similarity index 99% rename from dali/internal/window-system/tizen-wayland/display-connection-impl-ecore-wl.h rename to dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-impl-ecore-wl.h index 75f6888..8379ef3 100644 --- a/dali/internal/window-system/tizen-wayland/display-connection-impl-ecore-wl.h +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/display-connection-impl-ecore-wl.h @@ -33,6 +33,7 @@ namespace Dali class RenderSurface; class DisplayConnection; +class Window; namespace Internal { diff --git a/dali/internal/window-system/tizen-wayland/event-handler-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl/event-handler-ecore-wl.cpp similarity index 99% rename from dali/internal/window-system/tizen-wayland/event-handler-ecore-wl.cpp rename to dali/internal/window-system/tizen-wayland/ecore-wl/event-handler-ecore-wl.cpp index 89474e0..f1f159f 100755 --- a/dali/internal/window-system/tizen-wayland/event-handler-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/event-handler-ecore-wl.cpp @@ -25,8 +25,8 @@ #include #include #include -#include -//#include +#include +//#include #include #include @@ -53,7 +53,7 @@ // INTERNAL INCLUDES #include -#include +#include #include #include #include diff --git a/dali/internal/window-system/tizen-wayland/pixmap-render-surface-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl/pixmap-render-surface-ecore-wl.cpp similarity index 98% rename from dali/internal/window-system/tizen-wayland/pixmap-render-surface-ecore-wl.cpp rename to dali/internal/window-system/tizen-wayland/ecore-wl/pixmap-render-surface-ecore-wl.cpp index d8aa702..a39c5b1 100644 --- a/dali/internal/window-system/tizen-wayland/pixmap-render-surface-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/pixmap-render-surface-ecore-wl.cpp @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include +#include // EXTERNAL INCLUDES #include diff --git a/dali/internal/window-system/tizen-wayland/render-surface-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl/render-surface-ecore-wl.cpp similarity index 98% rename from dali/internal/window-system/tizen-wayland/render-surface-ecore-wl.cpp rename to dali/internal/window-system/tizen-wayland/ecore-wl/render-surface-ecore-wl.cpp index fbec6cd..988eca1 100644 --- a/dali/internal/window-system/tizen-wayland/render-surface-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/render-surface-ecore-wl.cpp @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include +#include // EXTERNAL INCLUDES #include diff --git a/dali/internal/window-system/tizen-wayland/window-impl-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl/window-impl-ecore-wl.cpp similarity index 99% rename from dali/internal/window-system/tizen-wayland/window-impl-ecore-wl.cpp rename to dali/internal/window-system/tizen-wayland/ecore-wl/window-impl-ecore-wl.cpp index fbcd0c6..c3c4801 100644 --- a/dali/internal/window-system/tizen-wayland/window-impl-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/window-impl-ecore-wl.cpp @@ -33,7 +33,7 @@ #include // INTERNAL HEADERS -#include +#include #include #include #include diff --git a/dali/internal/window-system/tizen-wayland/window-render-surface-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl/window-render-surface-ecore-wl.cpp similarity index 99% rename from dali/internal/window-system/tizen-wayland/window-render-surface-ecore-wl.cpp rename to dali/internal/window-system/tizen-wayland/ecore-wl/window-render-surface-ecore-wl.cpp index b5b7e0f..9e3578d 100644 --- a/dali/internal/window-system/tizen-wayland/window-render-surface-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/window-render-surface-ecore-wl.cpp @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include +#include // EXTERNAL INCLUDES #include diff --git a/dali/internal/window-system/tizen-wayland/window-render-surface-ecore-wl.h b/dali/internal/window-system/tizen-wayland/ecore-wl/window-render-surface-ecore-wl.h similarity index 98% rename from dali/internal/window-system/tizen-wayland/window-render-surface-ecore-wl.h rename to dali/internal/window-system/tizen-wayland/ecore-wl/window-render-surface-ecore-wl.h index 67b677c..30ffc52 100644 --- a/dali/internal/window-system/tizen-wayland/window-render-surface-ecore-wl.h +++ b/dali/internal/window-system/tizen-wayland/ecore-wl/window-render-surface-ecore-wl.h @@ -22,7 +22,7 @@ #include // INTERNAL INCLUDES -#include +#include #include namespace Dali diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-factory-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-factory-ecore-wl2.cpp new file mode 100644 index 0000000..e34e802 --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-factory-ecore-wl2.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 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 +#include + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ + + + +std::unique_ptr DisplayConnectionFactoryEcoreWl2::CreateDisplayConnection() +{ + return Utils::MakeUnique(); +} + +// this should be created from somewhere +std::unique_ptr GetDisplayConnectionFactory() +{ + // returns X display factory + return Utils::MakeUnique(); +} + +void DisplayConnectionFactoryGetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) +{ + DisplayConnectionEcoreWl2::GetDpi( dpiHorizontal, dpiVertical ); +} + +void DisplayConnectionFactoryGetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical) +{ + DisplayConnectionEcoreWl2::GetDpi( nativeWindow, dpiHorizontal, dpiVertical ); +} + +} +} +} diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-factory-ecore-wl2.h b/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-factory-ecore-wl2.h new file mode 100644 index 0000000..63f5646 --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-factory-ecore-wl2.h @@ -0,0 +1,42 @@ +#ifndef DALI_INTERNAL_WINDOWSYSTEM_ECOREWL_DISPLAY_CONNECTION_FACTORY_ECORE_WL2_H +#define DALI_INTERNAL_WINDOWSYSTEM_ECOREWL_DISPLAY_CONNECTION_FACTORY_ECORE_WL2_H + +/* + * Copyright (c) 2017 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 +#include +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ +class DisplayConnectionFactoryEcoreWl2 : public DisplayConnectionFactory +{ +public: + std::unique_ptr CreateDisplayConnection() override; +}; + +} // Adaptor + +} // Internal + +} // Dali + + +#endif // DALI_INTERNAL_WINDOWSYSTEM_ECOREWL_DISPLAY_CONNECTION_FACTORY_ECORE_WL2_H diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-impl-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-impl-ecore-wl2.cpp new file mode 100644 index 0000000..242914b --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-impl-ecore-wl2.cpp @@ -0,0 +1,149 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL_HEADERS +#include +#include + +// INTERNAL HEADERS +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +DisplayConnection* DisplayConnectionEcoreWl2::New() +{ + DisplayConnection* pDisplayConnection(new DisplayConnectionEcoreWl2()); + + return pDisplayConnection; +} + +DisplayConnectionEcoreWl2::DisplayConnectionEcoreWl2() +: mDisplay( NULL ), + mSurfaceType( RenderSurface::ECORE_RENDER_SURFACE ) +{ +} + +DisplayConnectionEcoreWl2::~DisplayConnectionEcoreWl2() +{ + if( mSurfaceType == RenderSurface::NATIVE_RENDER_SURFACE ) + { + ReleaseNativeDisplay(); + } +} + +Any DisplayConnectionEcoreWl2::GetDisplay() +{ + return Any( mDisplay ); +} + +void DisplayConnectionEcoreWl2::ConsumeEvents() +{ +} + +bool DisplayConnectionEcoreWl2::InitializeEgl(EglInterface& egl) +{ + EglImplementation& eglImpl = static_cast(egl); + + if( !eglImpl.InitializeGles( mDisplay ) ) + { + DALI_LOG_ERROR("Failed to initialize GLES.\n"); + return false; + } + + return true; +} + +void DisplayConnectionEcoreWl2::SetSurfaceType( RenderSurface::Type type ) +{ + mSurfaceType = type; + + if( mSurfaceType == RenderSurface::NATIVE_RENDER_SURFACE ) + { + mDisplay = GetNativeDisplay(); + } + else + { + Ecore_Wl2_Display* ecore_wl2_display = ecore_wl2_connected_display_get(NULL); + mDisplay = reinterpret_cast< EGLNativeDisplayType >( ecore_wl2_display_get(ecore_wl2_display) ); + } +} + +void DisplayConnectionEcoreWl2::GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) +{ + // calculate DPI + float xres, yres; + + // 1 inch = 25.4 millimeters +#if 0 + Ecore_Wl2_Window *ecore_wl2_window_find(unsigned int id); + Ecore_Wl2_Window *ecore_wl2_window_surface_find(struct wl_surface *surface); + + Ecore_Wl2_Output *ecore_wl2_window_output_find(Ecore_Wl2_Window *window); + ecore_wl2_window_output_find(wdata->win); + xres = ecore_wl2_output_dpi_get(); + yres = ecore_wl2_output_dpi_get(); +#endif + xres = 293.0; + yres = 293.0; + dpiHorizontal = int(xres + 0.5f); // rounding + dpiVertical = int(yres + 0.5f); +} + +void DisplayConnectionEcoreWl2::GetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical) +{ + // calculate DPI + float xres, yres; + + Ecore_Wl2_Output *wl2_output = ecore_wl2_window_output_find(AnyCast( nativeWindow )); + + if (!wl2_output) + { + DALI_LOG_ERROR("Failed to get Ecore_Wl2_Output.\n"); + return; + } + xres = ecore_wl2_output_dpi_get(wl2_output); + yres = ecore_wl2_output_dpi_get(wl2_output); + + dpiHorizontal = int(xres + 0.5f); // rounding + dpiVertical = int(yres + 0.5f); +} + +EGLNativeDisplayType DisplayConnectionEcoreWl2::GetNativeDisplay() +{ + return EGLNativeDisplayType(); +} + +void DisplayConnectionEcoreWl2::ReleaseNativeDisplay() +{ + +} + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-impl-ecore-wl2.h b/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-impl-ecore-wl2.h new file mode 100644 index 0000000..ca1813d --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/display-connection-impl-ecore-wl2.h @@ -0,0 +1,132 @@ +#ifndef DALI_INTERNAL_WINDOWSYSTEM_ECOREWL_DISPLAY_CONNECTION_IMPL_ECORE_WL2_H +#define DALI_INTERNAL_WINDOWSYSTEM_ECOREWL_DISPLAY_CONNECTION_IMPL_ECORE_WL2_H + +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +class RenderSurface; +class DisplayConnection; + +namespace Internal +{ + +namespace Adaptor +{ + +/** + * DisplayConnection implementation + */ +class DisplayConnectionEcoreWl2 : public Dali::Internal::Adaptor::DisplayConnection +{ +public: + + /** + * @brief Default constructor + */ + DisplayConnectionEcoreWl2(); + + /** + * @brief Create an initialized DisplayConnection. + * + * @return A handle to a newly allocated DisplayConnection resource. + */ + static DisplayConnection* New(); + +public: + + /** + * @copydoc Dali::DisplayConnection::GetDisplay + */ + Any GetDisplay(); + + /** + * @copydoc Dali::DisplayConnection::GetDpi + */ + static void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical); + + /** + * @copydoc Dali::DisplayConnection::GetDpi with native window + */ + static void GetDpi(Any nativeWindow, unsigned int& dpiHorizontal, unsigned int& dpiVertical); + + /** + * @copydoc Dali::DisplayConnection::ConsumeEvents + */ + void ConsumeEvents(); + + /** + * @copydoc Dali::DisplayConnection::InitializeEgl + */ + bool InitializeEgl(EglInterface& egl); + + /** + * @brief Sets surface type + */ + void SetSurfaceType( RenderSurface::Type type ); + + + +public: + + /** + * Destructor + */ + virtual ~DisplayConnectionEcoreWl2(); + +protected: + + /** + * @brief Gets display connection for native surface + */ + EGLNativeDisplayType GetNativeDisplay(); + + /** + * @brief Release display connection for native surface + */ + void ReleaseNativeDisplay(); + + // Undefined + DisplayConnectionEcoreWl2(const DisplayConnectionEcoreWl2&); + + // Undefined + DisplayConnectionEcoreWl2& operator=(const DisplayConnectionEcoreWl2& rhs); + +private: + EGLNativeDisplayType mDisplay; ///< Wayland-display for rendering + RenderSurface::Type mSurfaceType; +}; + +} // namespace Adaptor + +} // namespace internal + +} // namespace Dali + +#endif // DALI_INTERNAL_WINDOWSYSTEM_ECOREWL_DISPLAY_CONNECTION_IMPL_ECORE_WL2_H diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/event-handler-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/event-handler-ecore-wl2.cpp new file mode 100644 index 0000000..f3c94ef --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/event-handler-ecore-wl2.cpp @@ -0,0 +1,1692 @@ +/* + * Copyright (c) 2017 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 + +// EXTERNAL INCLUDES +// Ecore is littered with C style cast +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include +#include + +#ifdef DALI_ELDBUS_AVAILABLE +#include +#endif // DALI_ELDBUS_AVAILABLE + +#include +#include +//#include +#include + +#include + +#ifndef DALI_PROFILE_UBUNTU +#include +#include +#endif // DALI_PROFILE_UBUNTU + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +#if defined(DEBUG_ENABLED) +namespace +{ +Integration::Log::Filter* gTouchEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH"); +Integration::Log::Filter* gDragAndDropLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DND"); +Integration::Log::Filter* gImfLogging = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_IMF"); +Integration::Log::Filter* gSelectionEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_SELECTION"); +} // unnamed namespace +#endif + + +namespace +{ + +// DBUS accessibility +const char* BUS = "org.enlightenment.wm-screen-reader"; +const char* INTERFACE = "org.tizen.GestureNavigation"; +const char* PATH = "/org/tizen/GestureNavigation"; + +const unsigned int PRIMARY_TOUCH_BUTTON_ID( 1 ); + +const unsigned int BYTES_PER_CHARACTER_FOR_ATTRIBUTES = 3; + +#ifdef DALI_ELDBUS_AVAILABLE +// DBus gesture string matching lists. +// TODO: This needs moving to its own module. +const char * ElDBusAccessibilityFingerCountStrings[] = +{ + "OneFinger", + "TwoFingers", + "ThreeFingers" +}; +const unsigned int FingerCountStringsTotal = sizeof( ElDBusAccessibilityFingerCountStrings ) / sizeof( ElDBusAccessibilityFingerCountStrings[0] ); +enum GestureType +{ + GESTURE_TYPE_NONE, + GESTURE_TYPE_HOVER, + GESTURE_TYPE_SINGLE_TAP, + GESTURE_TYPE_DOUBLE_TAP, + GESTURE_TYPE_TRIPLE_TAP +}; +struct GestureTypeTable +{ + const char* name; + const GestureType type; +}; +GestureTypeTable ElDBusAccessibilityFullEventTypeStrings[] = +{ + { "Hover", GESTURE_TYPE_HOVER }, + { "SingleTap", GESTURE_TYPE_SINGLE_TAP }, + { "DoubleTap", GESTURE_TYPE_DOUBLE_TAP }, + { "TripleTap", GESTURE_TYPE_TRIPLE_TAP } +}; +const unsigned int FullEventTypeStringsTotal = sizeof( ElDBusAccessibilityFullEventTypeStrings ) / sizeof( ElDBusAccessibilityFullEventTypeStrings[0] ); +enum SubGestureType +{ + SUB_GESTURE_TYPE_NONE, + SUB_GESTURE_TYPE_FLICK +}; +struct SubGestureTypeTable +{ + const char* name; + const SubGestureType type; +}; +SubGestureTypeTable ElDBusAccessibilityDirectionalEventTypeStrings[] = +{ + { "Flick", SUB_GESTURE_TYPE_FLICK } +}; +const unsigned int DirectionalEventTypeStringsTotal = sizeof( ElDBusAccessibilityDirectionalEventTypeStrings ) / sizeof( ElDBusAccessibilityDirectionalEventTypeStrings[0] ); +enum GestureDirection +{ + GESTURE_DIRECTION_NONE, + GESTURE_DIRECTION_UP, + GESTURE_DIRECTION_DOWN, + GESTURE_DIRECTION_LEFT, + GESTURE_DIRECTION_RIGHT, + GESTURE_DIRECTION_UP_RETURN, + GESTURE_DIRECTION_DOWN_RETURN, + GESTURE_DIRECTION_LEFT_RETURN, + GESTURE_DIRECTION_RIGHT_RETURN +}; +struct GestureDirectionTable +{ + const char* name; + const GestureDirection direction; +}; +GestureDirectionTable ElDBusAccessibilityDirectionStrings[] = +{ + { "Up", GESTURE_DIRECTION_UP }, + { "Down", GESTURE_DIRECTION_DOWN }, + { "Left", GESTURE_DIRECTION_LEFT }, + { "Right", GESTURE_DIRECTION_RIGHT }, + { "UpReturn", GESTURE_DIRECTION_UP_RETURN }, + { "DownReturn", GESTURE_DIRECTION_DOWN_RETURN }, + { "LeftReturn", GESTURE_DIRECTION_LEFT_RETURN }, + { "RightReturn", GESTURE_DIRECTION_RIGHT_RETURN } +}; +const unsigned int DirectionStringsTotal = sizeof( ElDBusAccessibilityDirectionStrings ) / sizeof( ElDBusAccessibilityDirectionStrings[0] ); +#endif // DALI_ELDBUS_AVAILABLE + +/** + * EcoreInputModifierToEcoreIMFLock function converts from Ecore_Event_Modifier to Ecore_IMF_Keyboard_Locks enums. + * @param[in] modifier the Ecore_Event_Modifier input. + * @return the Ecore_IMF_Keyboard_Locks output. + */ +Ecore_IMF_Keyboard_Locks EcoreInputModifierToEcoreIMFLock( unsigned int modifier ) +{ + unsigned int lock( ECORE_IMF_KEYBOARD_LOCK_NONE ); // If no other matches, returns NONE. + + if( modifier & ECORE_EVENT_LOCK_NUM ) + { + lock |= ECORE_IMF_KEYBOARD_LOCK_NUM; // Num lock is active. + } + + if( modifier & ECORE_EVENT_LOCK_CAPS ) + { + lock |= ECORE_IMF_KEYBOARD_LOCK_CAPS; // Caps lock is active. + } + + if( modifier & ECORE_EVENT_LOCK_SCROLL ) + { + lock |= ECORE_IMF_KEYBOARD_LOCK_SCROLL; // Scroll lock is active. + } + + return static_cast( lock ); +} + +/** + * Ecore_Event_Modifier enums in Ecore_Input.h do not match Ecore_IMF_Keyboard_Modifiers in Ecore_IMF.h. + * This function converts from Ecore_Event_Modifier to Ecore_IMF_Keyboard_Modifiers enums. + * @param[in] ecoreModifier the Ecore_Event_Modifier input. + * @return the Ecore_IMF_Keyboard_Modifiers output. + */ +Ecore_IMF_Keyboard_Modifiers EcoreInputModifierToEcoreIMFModifier(unsigned int ecoreModifier) +{ + unsigned int modifier( ECORE_IMF_KEYBOARD_MODIFIER_NONE ); // If no other matches returns NONE. + + + if ( ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT ) // enums from ecore_input/Ecore_Input.h + { + modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT; // enums from ecore_imf/ecore_imf.h + } + + if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALT ) + { + modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT; + } + + if ( ecoreModifier & ECORE_EVENT_MODIFIER_CTRL ) + { + modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL; + } + + if ( ecoreModifier & ECORE_EVENT_MODIFIER_WIN ) + { + modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN; + } + + if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR ) + { + modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR; + } + + return static_cast( modifier ); +} + + +// Copied from x server +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); +} + +#ifndef DALI_PROFILE_UBUNTU +const char * DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE = "db/setting/accessibility/font_name"; // It will be update at vconf-key.h and replaced. +#endif // DALI_PROFILE_UBUNTU + +/** + * Get the device name from the provided ecore key event + */ +void GetDeviceName( Ecore_Event_Key* keyEvent, std::string& result ) +{ + const char* ecoreDeviceName = ecore_device_name_get( keyEvent->dev ); + + if ( ecoreDeviceName ) + { + result = ecoreDeviceName; + } +} + +/** + * Get the device class from the provided ecore event + */ +void GetDeviceClass( Ecore_Device_Class ecoreDeviceClass, Device::Class::Type& deviceClass ) +{ + switch( ecoreDeviceClass ) + { + case ECORE_DEVICE_CLASS_SEAT: + { + deviceClass = Device::Class::USER; + break; + } + case ECORE_DEVICE_CLASS_KEYBOARD: + { + deviceClass = Device::Class::KEYBOARD; + break; + } + case ECORE_DEVICE_CLASS_MOUSE: + { + deviceClass = Device::Class::MOUSE; + break; + } + case ECORE_DEVICE_CLASS_TOUCH: + { + deviceClass = Device::Class::TOUCH; + break; + } + case ECORE_DEVICE_CLASS_PEN: + { + deviceClass = Device::Class::PEN; + break; + } + case ECORE_DEVICE_CLASS_POINTER: + { + deviceClass = Device::Class::POINTER; + break; + } + case ECORE_DEVICE_CLASS_GAMEPAD: + { + deviceClass = Device::Class::GAMEPAD; + break; + } + default: + { + deviceClass = Device::Class::NONE; + break; + } + } +} + +void GetDeviceSubclass( Ecore_Device_Subclass ecoreDeviceSubclass, Device::Subclass::Type& deviceSubclass ) +{ + switch( ecoreDeviceSubclass ) + { + case ECORE_DEVICE_SUBCLASS_FINGER: + { + deviceSubclass = Device::Subclass::FINGER; + break; + } + case ECORE_DEVICE_SUBCLASS_FINGERNAIL: + { + deviceSubclass = Device::Subclass::FINGERNAIL; + break; + } + case ECORE_DEVICE_SUBCLASS_KNUCKLE: + { + deviceSubclass = Device::Subclass::KNUCKLE; + break; + } + case ECORE_DEVICE_SUBCLASS_PALM: + { + deviceSubclass = Device::Subclass::PALM; + break; + } + case ECORE_DEVICE_SUBCLASS_HAND_SIZE: + { + deviceSubclass = Device::Subclass::HAND_SIDE; + break; + } + case ECORE_DEVICE_SUBCLASS_HAND_FLAT: + { + deviceSubclass = Device::Subclass::HAND_FLAT; + break; + } + case ECORE_DEVICE_SUBCLASS_PEN_TIP: + { + deviceSubclass = Device::Subclass::PEN_TIP; + break; + } + case ECORE_DEVICE_SUBCLASS_TRACKPAD: + { + deviceSubclass = Device::Subclass::TRACKPAD; + break; + } + case ECORE_DEVICE_SUBCLASS_TRACKPOINT: + { + deviceSubclass = Device::Subclass::TRACKPOINT; + break; + } + case ECORE_DEVICE_SUBCLASS_TRACKBALL: + { + deviceSubclass = Device::Subclass::TRACKBALL; + break; + } +#ifdef OVER_TIZEN_VERSION_4 + case ECORE_DEVICE_SUBCLASS_REMOCON: + { + deviceSubclass = Device::Subclass::REMOCON; + break; + } + case ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD: + { + deviceSubclass = Device::Subclass::VIRTUAL_KEYBOARD; + break; + } +#endif + default: + { + deviceSubclass = Device::Subclass::NONE; + break; + } + } +} + +} // unnamed namespace + +// Impl to hide EFL implementation. +struct EventHandler::Impl +{ + // Construction & Destruction + + /** + * Constructor + */ + Impl( EventHandler* handler, Ecore_Wl2_Window* window ) + : mHandler( handler ), + mEcoreEventHandler(), + mWindow( window ), + mRotationAngle( 0 ), + mWindowWidth( 0 ), + mWindowHeight( 0 ) +#ifdef DALI_ELDBUS_AVAILABLE + , mSystemConnection( NULL ) +#endif // DALI_ELDBUS_AVAILABLE + { + // Only register for touch and key events if we have a window + if ( window != 0 ) + { + // Register Touch events + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_BUTTON_DOWN, EcoreEventMouseButtonDown, handler ) ); + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_BUTTON_UP, EcoreEventMouseButtonUp, handler ) ); + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_MOVE, EcoreEventMouseButtonMove, handler ) ); + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_BUTTON_CANCEL, EcoreEventMouseButtonCancel, handler ) ); + + // Register Mouse wheel events + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_WHEEL, EcoreEventMouseWheel, handler ) ); + + // Register Focus events + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_WL2_EVENT_FOCUS_IN, EcoreEventWindowFocusIn, handler ) ); + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_WL2_EVENT_FOCUS_OUT, EcoreEventWindowFocusOut, handler ) ); + + // Register Key events + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_KEY_DOWN, EcoreEventKeyDown, handler ) ); + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_KEY_UP, EcoreEventKeyUp, handler ) ); + + // Register Selection event - clipboard selection + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_WL2_EVENT_DATA_SOURCE_SEND, EcoreEventDataSend, handler ) ); + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_WL2_EVENT_SELECTION_DATA_READY, EcoreEventDataReceive, handler ) ); + + // Register Rotate event + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_WL2_EVENT_WINDOW_ROTATE, EcoreEventRotate, handler) ); + + // Register Detent event + mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_DETENT_ROTATE, EcoreEventDetent, handler) ); + +#ifndef DALI_PROFILE_UBUNTU + // Register Vconf notify - font name and size + vconf_notify_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontNameChanged, handler ); + vconf_notify_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged, handler ); +#endif // DALI_PROFILE_UBUNTU + +#ifdef DALI_ELDBUS_AVAILABLE + // Initialize ElDBus. + DALI_LOG_INFO( gImfLogging, Debug::General, "Starting DBus Initialization\n" ); + + // Pass in handler. + EcoreElDBusInitialisation( handler ); + + DALI_LOG_INFO( gImfLogging, Debug::General, "Finished DBus Initialization\n" ); +#endif // DALI_ELDBUS_AVAILABLE + } + } + + /** + * Destructor + */ + ~Impl() + { +#ifndef DALI_PROFILE_UBUNTU + vconf_ignore_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged ); + vconf_ignore_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontNameChanged ); +#endif // DALI_PROFILE_UBUNTU + + for( std::vector::iterator iter = mEcoreEventHandler.begin(), endIter = mEcoreEventHandler.end(); iter != endIter; ++iter ) + { + ecore_event_handler_del( *iter ); + } + +#ifdef DALI_ELDBUS_AVAILABLE + // Close down ElDBus connections. + if( mSystemConnection ) + { + eldbus_connection_unref( mSystemConnection ); + } +#endif // DALI_ELDBUS_AVAILABLE + } + + // Static methods + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Touch Callbacks + ///////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Called when a touch down is received. + */ + static Eina_Bool EcoreEventMouseButtonDown( void* data, int type, void* event ) + { + Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event ); + EventHandler* handler( (EventHandler*)data ); + + if ( touchEvent->window == (unsigned int)ecore_wl2_window_id_get(handler->mImpl->mWindow) ) + { + PointState::Type state ( PointState::DOWN ); + + // Check if the buttons field is set and ensure it's the primary touch button. + // If this event was triggered by buttons other than the primary button (used for touch), then + // just send an interrupted event to Core. + if ( touchEvent->buttons && (touchEvent->buttons != PRIMARY_TOUCH_BUTTON_ID ) ) + { + state = PointState::INTERRUPTED; + } + + Device::Class::Type deviceClass; + Device::Subclass::Type deviceSubclass; + + GetDeviceClass( ecore_device_class_get( touchEvent->dev ), deviceClass ); + GetDeviceSubclass( ecore_device_subclass_get( touchEvent->dev ), deviceSubclass ); + + Integration::Point point; + point.SetDeviceId( touchEvent->multi.device ); + point.SetState( state ); + point.SetScreenPosition( Vector2( touchEvent->x, touchEvent->y ) ); + point.SetRadius( touchEvent->multi.radius, Vector2( touchEvent->multi.radius_x, touchEvent->multi.radius_y ) ); + point.SetPressure( touchEvent->multi.pressure ); + point.SetAngle( Degree( touchEvent->multi.angle ) ); + point.SetDeviceClass( deviceClass ); + point.SetDeviceSubclass( deviceSubclass ); + + handler->SendEvent( point, touchEvent->timestamp ); + } + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a touch up is received. + */ + static Eina_Bool EcoreEventMouseButtonUp( void* data, int type, void* event ) + { + Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event ); + EventHandler* handler( (EventHandler*)data ); + + if ( touchEvent->window == (unsigned int)ecore_wl2_window_id_get(handler->mImpl->mWindow) ) + { + Device::Class::Type deviceClass; + Device::Subclass::Type deviceSubclass; + + GetDeviceClass( ecore_device_class_get( touchEvent->dev ), deviceClass ); + GetDeviceSubclass( ecore_device_subclass_get( touchEvent->dev ), deviceSubclass ); + + Integration::Point point; + point.SetDeviceId( touchEvent->multi.device ); + point.SetState( PointState::UP ); + point.SetScreenPosition( Vector2( touchEvent->x, touchEvent->y ) ); + point.SetRadius( touchEvent->multi.radius, Vector2( touchEvent->multi.radius_x, touchEvent->multi.radius_y ) ); + point.SetPressure( touchEvent->multi.pressure ); + point.SetAngle( Degree( touchEvent->multi.angle ) ); + point.SetDeviceClass( deviceClass ); + point.SetDeviceSubclass( deviceSubclass ); + + handler->SendEvent( point, touchEvent->timestamp ); + } + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a touch motion is received. + */ + static Eina_Bool EcoreEventMouseButtonMove( void* data, int type, void* event ) + { + Ecore_Event_Mouse_Move *touchEvent( (Ecore_Event_Mouse_Move*)event ); + EventHandler* handler( (EventHandler*)data ); + + if ( touchEvent->window == (unsigned int)ecore_wl2_window_id_get(handler->mImpl->mWindow) ) + { + Device::Class::Type deviceClass; + Device::Subclass::Type deviceSubclass; + + GetDeviceClass( ecore_device_class_get( touchEvent->dev ), deviceClass ); + GetDeviceSubclass( ecore_device_subclass_get( touchEvent->dev ), deviceSubclass ); + + Integration::Point point; + point.SetDeviceId( touchEvent->multi.device ); + point.SetState( PointState::MOTION ); + point.SetScreenPosition( Vector2( touchEvent->x, touchEvent->y ) ); + point.SetRadius( touchEvent->multi.radius, Vector2( touchEvent->multi.radius_x, touchEvent->multi.radius_y ) ); + point.SetPressure( touchEvent->multi.pressure ); + point.SetAngle( Degree( touchEvent->multi.angle ) ); + point.SetDeviceClass( deviceClass ); + point.SetDeviceSubclass( deviceSubclass ); + + handler->SendEvent( point, touchEvent->timestamp ); + } + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a touch is canceled. + */ + static Eina_Bool EcoreEventMouseButtonCancel( void* data, int type, void* event ) + { + Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event ); + EventHandler* handler( (EventHandler*)data ); + + if( touchEvent->window == (unsigned int)ecore_wl2_window_id_get( handler->mImpl->mWindow ) ) + { + Integration::Point point; + point.SetDeviceId( touchEvent->multi.device ); + point.SetState( PointState::INTERRUPTED ); + point.SetScreenPosition( Vector2( 0.0f, 0.0f ) ); + handler->SendEvent( point, touchEvent->timestamp ); + + DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT EcoreEventMouseButtonCancel\n" ); + } + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a mouse wheel is received. + */ + static Eina_Bool EcoreEventMouseWheel( void* data, int type, void* event ) + { + Ecore_Event_Mouse_Wheel *mouseWheelEvent( (Ecore_Event_Mouse_Wheel*)event ); + + DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT Ecore_Event_Mouse_Wheel: direction: %d, modifiers: %d, x: %d, y: %d, z: %d\n", mouseWheelEvent->direction, mouseWheelEvent->modifiers, mouseWheelEvent->x, mouseWheelEvent->y, mouseWheelEvent->z); + + EventHandler* handler( (EventHandler*)data ); + if ( mouseWheelEvent->window == (unsigned int)ecore_wl2_window_id_get(handler->mImpl->mWindow) ) + { + WheelEvent wheelEvent( WheelEvent::MOUSE_WHEEL, mouseWheelEvent->direction, mouseWheelEvent->modifiers, Vector2(mouseWheelEvent->x, mouseWheelEvent->y), mouseWheelEvent->z, mouseWheelEvent->timestamp ); + handler->SendWheelEvent( wheelEvent ); + } + return ECORE_CALLBACK_PASS_ON; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Key Callbacks + ///////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Called when a key down is received. + */ + static Eina_Bool EcoreEventKeyDown( void* data, int type, void* event ) + { + DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventKeyDown \n" ); + + EventHandler* handler( (EventHandler*)data ); + Ecore_Event_Key *keyEvent( (Ecore_Event_Key*)event ); + bool eventHandled( false ); + + // If a device key then skip ecore_imf_context_filter_event. + if ( ! KeyLookup::IsDeviceButton( keyEvent->keyname ) ) + { + Ecore_IMF_Context* imfContext = NULL; + Dali::ImfManager imfManager( ImfManager::Get() ); + if ( imfManager ) + { + imfContext = reinterpret_cast(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 ecoreKeyDownEvent; + ecoreKeyDownEvent.keyname = keyEvent->keyname; + ecoreKeyDownEvent.key = keyEvent->key; + ecoreKeyDownEvent.string = keyEvent->string; + ecoreKeyDownEvent.compose = keyEvent->compose; + ecoreKeyDownEvent.timestamp = keyEvent->timestamp; + ecoreKeyDownEvent.modifiers = EcoreInputModifierToEcoreIMFModifier ( keyEvent->modifiers ); + ecoreKeyDownEvent.locks = EcoreInputModifierToEcoreIMFLock( keyEvent->modifiers ); + ecoreKeyDownEvent.dev_name = ecore_device_name_get( keyEvent->dev ); + ecoreKeyDownEvent.dev_class = static_cast( ecore_device_class_get( keyEvent->dev ) ); + ecoreKeyDownEvent.dev_subclass = static_cast( ecore_device_subclass_get( keyEvent->dev ) ); + + std::string checkDevice; + GetDeviceName( keyEvent, checkDevice ); + + // If the device is IME and the focused key is the direction keys, then we should send a key event to move a key cursor. + if( ( checkDevice == "ime" ) && ( ( !strncmp( keyEvent->keyname, "Left", 4 ) ) || + ( !strncmp( keyEvent->keyname, "Right", 5 ) ) || + ( !strncmp( keyEvent->keyname, "Up", 2 ) ) || + ( !strncmp( keyEvent->keyname, "Down", 4 ) ) ) ) + { + eventHandled = 0; + } + else + { + eventHandled = ecore_imf_context_filter_event( imfContext, + ECORE_IMF_EVENT_KEY_DOWN, + (Ecore_IMF_Event *) &ecoreKeyDownEvent ); + } + + // If the event has not been handled by IMF then check if we should reset our IMF context + if( !eventHandled ) + { + if ( !strcmp( keyEvent->keyname, "Escape" ) || + !strcmp( keyEvent->keyname, "Return" ) || + !strcmp( keyEvent->keyname, "KP_Enter" ) ) + { + ecore_imf_context_reset( imfContext ); + } + } + } + } + + // If the event wasn't handled then we should send a key event. + if ( !eventHandled ) + { + if ( keyEvent->window == (unsigned int)ecore_wl2_window_id_get(handler->mImpl->mWindow) ) + { + std::string keyName( keyEvent->keyname ); + std::string keyString( "" ); + int keyCode = KeyLookup::GetDaliKeyCode( keyEvent->keyname); + keyCode = (keyCode == -1) ? 0 : keyCode; + int modifier( keyEvent->modifiers ); + unsigned long time = keyEvent->timestamp; + if (!strncmp(keyEvent->keyname, "Keycode-", 8)) + keyCode = atoi(keyEvent->keyname + 8); + + // Ensure key event string is not NULL as keys like SHIFT have a null string. + if ( keyEvent->string ) + { + keyString = keyEvent->string; + } + + std::string deviceName; + Device::Class::Type deviceClass; + Device::Subclass::Type deviceSubclass; + + GetDeviceName( keyEvent, deviceName ); + GetDeviceClass( ecore_device_class_get( keyEvent->dev ), deviceClass ); + GetDeviceSubclass( ecore_device_subclass_get( keyEvent->dev ), deviceSubclass ); + + DALI_LOG_INFO( gImfLogging, Debug::Verbose, "EVENT EcoreEventKeyDown - >>EcoreEventKeyDown deviceName(%s) deviceClass(%d)\n", deviceName.c_str(), deviceClass ); + + Integration::KeyEvent keyEvent(keyName, keyString, keyCode, modifier, time, Integration::KeyEvent::Down, deviceName, deviceClass, deviceSubclass ); + handler->SendEvent( keyEvent ); + } + } + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a key up is received. + */ + static Eina_Bool EcoreEventKeyUp( void* data, int type, void* event ) + { + DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventKeyUp\n" ); + + EventHandler* handler( (EventHandler*)data ); + Ecore_Event_Key *keyEvent( (Ecore_Event_Key*)event ); + bool eventHandled( false ); + + // Device keys like Menu, home, back button must skip ecore_imf_context_filter_event. + if ( ! KeyLookup::IsDeviceButton( keyEvent->keyname ) ) + { + Ecore_IMF_Context* imfContext = NULL; + Dali::ImfManager imfManager( ImfManager::Get() ); + if ( imfManager ) + { + imfContext = reinterpret_cast(ImfManager::GetImplementation( imfManager ).GetContext()); + } + + if ( imfContext ) + { + // We're consuming key up event so we have to pass to IMF so that it can parse it as well. + Ecore_IMF_Event_Key_Up ecoreKeyUpEvent; + ecoreKeyUpEvent.keyname = keyEvent->keyname; + ecoreKeyUpEvent.key = keyEvent->key; + ecoreKeyUpEvent.string = keyEvent->string; + ecoreKeyUpEvent.compose = keyEvent->compose; + ecoreKeyUpEvent.timestamp = keyEvent->timestamp; + ecoreKeyUpEvent.modifiers = EcoreInputModifierToEcoreIMFModifier ( keyEvent->modifiers ); + ecoreKeyUpEvent.locks = EcoreInputModifierToEcoreIMFLock( keyEvent->modifiers ); + ecoreKeyUpEvent.dev_name = ecore_device_name_get( keyEvent->dev ); + ecoreKeyUpEvent.dev_class = static_cast( ecore_device_class_get( keyEvent->dev ) ); + ecoreKeyUpEvent.dev_subclass = static_cast( ecore_device_subclass_get( keyEvent->dev ) ); + + eventHandled = ecore_imf_context_filter_event( imfContext, + ECORE_IMF_EVENT_KEY_UP, + (Ecore_IMF_Event *) &ecoreKeyUpEvent ); + } + } + + // If the event wasn't handled then we should send a key event. + if ( !eventHandled ) + { + if ( keyEvent->window == (unsigned int)ecore_wl2_window_id_get(handler->mImpl->mWindow) ) + { + std::string keyName( keyEvent->keyname ); + std::string keyString( "" ); + int keyCode = KeyLookup::GetDaliKeyCode( keyEvent->keyname); + keyCode = (keyCode == -1) ? 0 : keyCode; + int modifier( keyEvent->modifiers ); + unsigned long time = keyEvent->timestamp; + if (!strncmp(keyEvent->keyname, "Keycode-", 8)) + keyCode = atoi(keyEvent->keyname + 8); + + // Ensure key event string is not NULL as keys like SHIFT have a null string. + if ( keyEvent->string ) + { + keyString = keyEvent->string; + } + + std::string deviceName; + Device::Class::Type deviceClass; + Device::Subclass::Type deviceSubclass; + + GetDeviceName( keyEvent, deviceName ); + GetDeviceClass( ecore_device_class_get( keyEvent->dev ), deviceClass ); + GetDeviceSubclass( ecore_device_subclass_get( keyEvent->dev ), deviceSubclass ); + + Integration::KeyEvent keyEvent(keyName, keyString, keyCode, modifier, time, Integration::KeyEvent::Up, deviceName, deviceClass, deviceSubclass ); + handler->SendEvent( keyEvent ); + } + } + + return ECORE_CALLBACK_PASS_ON; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Window Callbacks + ///////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Called when the window gains focus. + */ + static Eina_Bool EcoreEventWindowFocusIn( void* data, int type, void* event ) + { + Ecore_Wl2_Event_Focus_In* focusInEvent( (Ecore_Wl2_Event_Focus_In*)event ); + EventHandler* handler( (EventHandler*)data ); + + DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventWindowFocusIn \n" ); + + // If the window gains focus and we hid the keyboard then show it again. + if ( focusInEvent->window == (unsigned int)ecore_wl2_window_id_get(handler->mImpl->mWindow) ) + { + DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT EcoreEventWindowFocusIn - >>WindowFocusGained \n" ); + + if ( ImfManager::IsAvailable() /* Only get the ImfManager if it's available as we do not want to create it */ ) + { + Dali::ImfManager imfManager( ImfManager::Get() ); + if ( imfManager ) + { + ImfManager& imfManagerImpl( ImfManager::GetImplementation( imfManager ) ); + if( imfManagerImpl.RestoreAfterFocusLost() ) + { + imfManagerImpl.Activate(); + } + } + } + Dali::Clipboard clipboard = Clipboard::Get(); + clipboard.HideClipboard(); + } + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when the window loses focus. + */ + static Eina_Bool EcoreEventWindowFocusOut( void* data, int type, void* event ) + { + Ecore_Wl2_Event_Focus_Out* focusOutEvent( (Ecore_Wl2_Event_Focus_Out*)event ); + EventHandler* handler( (EventHandler*)data ); + + DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventWindowFocusOut \n" ); + + // If the window loses focus then hide the keyboard. + if ( focusOutEvent->window == (unsigned int)ecore_wl2_window_id_get(handler->mImpl->mWindow) ) + { + if ( ImfManager::IsAvailable() /* Only get the ImfManager if it's available as we do not want to create it */ ) + { + Dali::ImfManager imfManager( ImfManager::Get() ); + if ( imfManager ) + { + ImfManager& imfManagerImpl( ImfManager::GetImplementation( imfManager ) ); + if( imfManagerImpl.RestoreAfterFocusLost() ) + { + imfManagerImpl.Deactivate(); + } + } + } + + // Hiding clipboard event will be ignored once because window focus out event is always received on showing clipboard + Dali::Clipboard clipboard = Clipboard::Get(); + if ( clipboard ) + { + Clipboard& clipBoardImpl( GetImplementation( clipboard ) ); + clipBoardImpl.HideClipboard(true); + } + } + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when the window is damaged. + */ + static Eina_Bool EcoreEventWindowDamaged(void *data, int type, void *event) + { + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when the window properties are changed. + * We are only interested in the font change. + */ + + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Drag & Drop Callbacks + ///////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Called when a dragged item enters our window's bounds. + * This is when items are dragged INTO our window. + */ + static Eina_Bool EcoreEventDndEnter( void* data, int type, void* event ) + { + DALI_LOG_INFO( gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndEnter\n" ); + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a dragged item is moved within our window. + * This is when items are dragged INTO our window. + */ + static Eina_Bool EcoreEventDndPosition( void* data, int type, void* event ) + { + DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndPosition\n" ); + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a dragged item leaves our window's bounds. + * This is when items are dragged INTO our window. + */ + static Eina_Bool EcoreEventDndLeave( void* data, int type, void* event ) + { + DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndLeave\n" ); + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when the dragged item is dropped within our window's bounds. + * This is when items are dragged INTO our window. + */ + static Eina_Bool EcoreEventDndDrop( void* data, int type, void* event ) + { + DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndDrop\n" ); + + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a dragged item is moved from our window and the target window has done processing it. + * This is when items are dragged FROM our window. + */ + static Eina_Bool EcoreEventDndFinished( void* data, int type, void* event ) + { + DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndFinished\n" ); + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when a dragged item is moved from our window and the target window has sent us a status. + * This is when items are dragged FROM our window. + */ + static Eina_Bool EcoreEventDndStatus( void* data, int type, void* event ) + { + DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndStatus\n" ); + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when the client messages (i.e. the accessibility events) are received. + */ + static Eina_Bool EcoreEventClientMessage( void* data, int type, void* event ) + { + return ECORE_CALLBACK_PASS_ON; + } + + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // ElDBus Accessibility Callbacks + ///////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef DALI_ELDBUS_AVAILABLE + // Callback for Ecore ElDBus accessibility events. + static void OnEcoreElDBusAccessibilityNotification( void *context EINA_UNUSED, const Eldbus_Message *message ) + { + EventHandler* handler = static_cast< EventHandler* >( context ); + // Ignore any accessibility events when paused. + if( handler->mPaused ) + { + return; + } + + if( !handler->mAccessibilityAdaptor ) + { + DALI_LOG_ERROR( "Invalid accessibility adaptor\n" ); + return; + } + + AccessibilityAdaptor* accessibilityAdaptor( &AccessibilityAdaptor::GetImplementation( handler->mAccessibilityAdaptor ) ); + if( !accessibilityAdaptor ) + { + DALI_LOG_ERROR( "Cannot access accessibility adaptor\n" ); + return; + } + + int gestureValue; + int xS, yS, xE, yE; + int state; // 0 - begin, 1 - ongoing, 2 - ended, 3 - aborted + int eventTime; + + // The string defines the arg-list's respective types. + if( !eldbus_message_arguments_get( message, "iiiiiiu", &gestureValue, &xS, &yS, &xE, &yE, &state, &eventTime ) ) + { + DALI_LOG_ERROR( "OnEcoreElDBusAccessibilityNotification: Error getting arguments\n" ); + } + + DALI_LOG_INFO( gImfLogging, Debug::General, "Got gesture: Name: %d Args: %d,%d,%d,%d State: %d\n", gestureValue, xS, yS, xE, yE ); + + // Create a touch point object. + TouchPoint::State touchPointState( TouchPoint::Down ); + if( state == 0 ) + { + touchPointState = TouchPoint::Down; // Mouse down. + } + else if( state == 1 ) + { + touchPointState = TouchPoint::Motion; // Mouse move. + } + else if( state == 2 ) + { + touchPointState = TouchPoint::Up; // Mouse up. + } + else + { + touchPointState = TouchPoint::Interrupted; // Error. + } + + // Send touch event to accessibility adaptor. + TouchPoint point( 0, touchPointState, (float)xS, (float)yS ); + + // Perform actions based on received gestures. + // Note: This is seperated from the reading so we can have other input readers without changing the below code. + switch( gestureValue ) + { + case 0: // OneFingerHover + { + // Focus, read out. + accessibilityAdaptor->HandleActionReadEvent( (unsigned int)xS, (unsigned int)yS, true /* allow read again */ ); + break; + } + case 1: // TwoFingersHover + { + // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control + accessibilityAdaptor->HandleActionScrollEvent( point, GetCurrentMilliSeconds() ); + break; + } + case 2: // ThreeFingersHover + { + // Read from top item on screen continuously. + accessibilityAdaptor->HandleActionReadFromTopEvent(); + break; + } + case 3: // OneFingerFlickLeft + { + // Move to previous item. + accessibilityAdaptor->HandleActionReadPreviousEvent(); + break; + } + case 4: // OneFingerFlickRight + { + // Move to next item. + accessibilityAdaptor->HandleActionReadNextEvent(); + break; + } + case 5: // OneFingerFlickUp + { + // Move to previous item. + accessibilityAdaptor->HandleActionPreviousEvent(); + break; + } + case 6: // OneFingerFlickDown + { + // Move to next item. + accessibilityAdaptor->HandleActionNextEvent(); + break; + } + case 7: // TwoFingersFlickUp + { + // Scroll up the list. + accessibilityAdaptor->HandleActionScrollUpEvent(); + break; + } + case 8: // TwoFingersFlickDown + { + // Scroll down the list. + accessibilityAdaptor->HandleActionScrollDownEvent(); + break; + } + case 9: // TwoFingersFlickLeft + { + // Scroll left to the previous page + accessibilityAdaptor->HandleActionPageLeftEvent(); + break; + } + case 10: // TwoFingersFlickRight + { + // Scroll right to the next page + accessibilityAdaptor->HandleActionPageRightEvent(); + break; + } + case 11: // ThreeFingersFlickLeft + { + // Not exist yet + break; + } + case 12: // ThreeFingersFlickRight + { + // Not exist yet + break; + } + case 13: // ThreeFingersFlickUp + { + // Not exist yet + break; + } + case 14: // ThreeFingersFlickDown + { + // Not exist yet + break; + } + case 15: // OneFingerSingleTap + { + // Focus, read out. + accessibilityAdaptor->HandleActionReadEvent( (unsigned int)xS, (unsigned int)yS, true /* allow read again */ ); + break; + } + case 16: // OneFingerDoubleTap + { + // Activate selected item / active edit mode. + accessibilityAdaptor->HandleActionActivateEvent(); + break; + } + case 17: // OneFingerTripleTap + { + // Zoom + accessibilityAdaptor->HandleActionZoomEvent(); + break; + } + case 18: // TwoFingersSingleTap + { + // Pause/Resume current speech + accessibilityAdaptor->HandleActionReadPauseResumeEvent(); + break; + } + case 19: // TwoFingersDoubleTap + { + // Start/Stop current action + accessibilityAdaptor->HandleActionStartStopEvent(); + break; + } + case 20: // TwoFingersTripleTap + { + // Read information from indicator + accessibilityAdaptor->HandleActionReadIndicatorInformationEvent(); + break; + } + case 21: // ThreeFingersSingleTap + { + // Read from top item on screen continuously. + accessibilityAdaptor->HandleActionReadFromTopEvent(); + break; + } + case 22: // ThreeFingersDoubleTap + { + // Read from next item continuously. + accessibilityAdaptor->HandleActionReadFromNextEvent(); + break; + } + case 23: // ThreeFingersTripleTap + { + // Not exist yet + break; + } + case 24: // OneFingerFlickLeftReturn + { + // Scroll up to the previous page + accessibilityAdaptor->HandleActionPageUpEvent(); + break; + } + case 25: // OneFingerFlickRightReturn + { + // Scroll down to the next page + accessibilityAdaptor->HandleActionPageDownEvent(); + break; + } + case 26: // OneFingerFlickUpReturn + { + // Move to the first item on screen + accessibilityAdaptor->HandleActionMoveToFirstEvent(); + break; + } + case 27: // OneFingerFlickDownReturn + { + // Move to the last item on screen + accessibilityAdaptor->HandleActionMoveToLastEvent(); + break; + } + case 28: // TwoFingersFlickLeftReturn + { + // Not exist yet + break; + } + case 29: // TwoFingersFlickRightReturn + { + // Not exist yet + break; + } + case 30: // TwoFingersFlickUpReturn + { + // Not exist yet + break; + } + case 31: // TwoFingersFlickDownReturn + { + // Not exist yet + break; + } + case 32: // ThreeFingersFlickLeftReturn + { + // Not exist yet + break; + } + case 33: // ThreeFingersFlickRightReturn + { + // Not exist yet + break; + } + case 34: // ThreeFingersFlickUpReturn + { + // Not exist yet + break; + } + case 35: // ThreeFingersFlickDownReturn + { + // Not exist yet + break; + } + } + } + + void EcoreElDBusInitialisation( void *handle ) + { + Eldbus_Object *object; + Eldbus_Proxy *manager; + + if( !( mSystemConnection = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM) ) ) + { + DALI_LOG_ERROR( "Unable to get system bus\n" ); + } + + object = eldbus_object_get( mSystemConnection, BUS, PATH ); + if( !object ) + { + DALI_LOG_ERROR( "Getting object failed\n" ); + return; + } + + manager = eldbus_proxy_get( object, INTERFACE ); + if( !manager ) + { + DALI_LOG_ERROR( "Getting proxy failed\n" ); + return; + } + + if( !eldbus_proxy_signal_handler_add( manager, "GestureDetected", OnEcoreElDBusAccessibilityNotification, handle ) ) + { + DALI_LOG_ERROR( "No signal handler returned\n" ); + } + } +#endif // DALI_ELDBUS_AVAILABLE + + /** + * Called when the source window notifies us the content in clipboard is selected. + */ + static Eina_Bool EcoreEventSelectionClear( void* data, int type, void* event ) + { + DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionClear\n" ); + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when the source window sends us about the selected content. + * For example, when dragged items are dragged INTO our window or when items are selected in the clipboard. + */ + static Eina_Bool EcoreEventSelectionNotify( void* data, int type, void* event ) + { + DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionNotify\n" ); + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when the source window notifies us the content in clipboard is selected. + */ + static Eina_Bool EcoreEventDataSend( void* data, int type, void* event ) + { + DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventDataSend\n" ); + + Dali::Clipboard clipboard = Clipboard::Get(); + if ( clipboard ) + { + Clipboard& clipBoardImpl( GetImplementation( clipboard ) ); + clipBoardImpl.ExcuteBuffered( true, event ); + } + return ECORE_CALLBACK_PASS_ON; + } + + /** + * Called when the source window sends us about the selected content. + * For example, when item is selected in the clipboard. + */ + static Eina_Bool EcoreEventDataReceive( void* data, int type, void* event ) + { + DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventDataReceive\n" ); + + EventHandler* handler( (EventHandler*)data ); + Dali::Clipboard clipboard = Clipboard::Get(); + char *selectionData = NULL; + if ( clipboard ) + { + Clipboard& clipBoardImpl( GetImplementation( clipboard ) ); + selectionData = clipBoardImpl.ExcuteBuffered( false, event ); + } + if ( selectionData && handler->mClipboardEventNotifier ) + { + ClipboardEventNotifier& clipboardEventNotifier( ClipboardEventNotifier::GetImplementation( handler->mClipboardEventNotifier ) ); + std::string content( selectionData, strlen(selectionData) ); + + clipboardEventNotifier.SetContent( content ); + clipboardEventNotifier.EmitContentSelectedSignal(); + } + return ECORE_CALLBACK_PASS_ON; + } + + /* + * Called when rotate event is recevied + */ + static Eina_Bool EcoreEventRotate( void* data, int type, void* event ) + { + DALI_LOG_INFO( gSelectionEventLogFilter, Debug::Concise, "EcoreEventRotate\n" ); + + EventHandler* handler( (EventHandler*)data ); + Ecore_Wl2_Event_Window_Rotation* ev( (Ecore_Wl2_Event_Window_Rotation*)event ); + + if( ev->win != (unsigned int)ecore_wl2_window_id_get( handler->mImpl->mWindow ) ) + { + return ECORE_CALLBACK_PASS_ON; + } + + RotationEvent rotationEvent; + rotationEvent.angle = ev->angle; + rotationEvent.winResize = 0; + + if( ev->angle == 0 || ev->angle == 180 ) + { + rotationEvent.width = ev->w; + rotationEvent.height = ev->h; + } + else + { + rotationEvent.width = ev->h; + rotationEvent.height = ev->w; + } + + handler->SendRotationPrepareEvent( rotationEvent ); + + return ECORE_CALLBACK_PASS_ON; + } + + /* + * Called when detent event is recevied + */ + static Eina_Bool EcoreEventDetent( void* data, int type, void* event ) + { + DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventDetent\n" ); + EventHandler* handler( (EventHandler*)data ); + Ecore_Event_Detent_Rotate *e((Ecore_Event_Detent_Rotate *)event); + int direction = (e->direction == ECORE_DETENT_DIRECTION_CLOCKWISE) ? 1 : -1; + int timeStamp = e->timestamp; + + WheelEvent wheelEvent( WheelEvent::CUSTOM_WHEEL, 0, 0, Vector2(0.0f, 0.0f), direction, timeStamp ); + handler->SendWheelEvent( wheelEvent ); + return ECORE_CALLBACK_PASS_ON; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Font Callbacks + ///////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Called when a font name is changed. + */ + static void VconfNotifyFontNameChanged( keynode_t* node, void* data ) + { + EventHandler* handler = static_cast( data ); + handler->SendEvent( StyleChange::DEFAULT_FONT_CHANGE ); + } + + /** + * Called when a font size is changed. + */ + static void VconfNotifyFontSizeChanged( keynode_t* node, void* data ) + { + EventHandler* handler = static_cast( data ); + handler->SendEvent( StyleChange::DEFAULT_FONT_SIZE_CHANGE ); + } + + void ConvertTouchPosition( Integration::Point& point ) + { + Vector2 position = point.GetScreenPosition(); + Vector2 convertedPosition; + + switch( mRotationAngle ) + { + case 90: + { + convertedPosition.x = mWindowWidth - position.y; + convertedPosition.y = position.x; + break; + } + case 180: + { + convertedPosition.x = mWindowWidth - position.x; + convertedPosition.y = mWindowHeight - position.y; + break; + } + case 270: + { + convertedPosition.x = position.y; + convertedPosition.y = mWindowHeight - position.x; + break; + } + default: + { + convertedPosition = position; + break; + } + } + + point.SetScreenPosition( convertedPosition ); + } + + // Data + EventHandler* mHandler; + std::vector mEcoreEventHandler; + Ecore_Wl2_Window* mWindow; + int mRotationAngle; + int mWindowWidth; + int mWindowHeight; +#ifdef DALI_ELDBUS_AVAILABLE + Eldbus_Connection* mSystemConnection; +#endif // DALI_ELDBUS_AVAILABLE +}; + +EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector ) +: mCoreEventInterface( coreEventInterface ), + mGestureManager( gestureManager ), + mStyleMonitor( StyleMonitor::Get() ), + mDamageObserver( damageObserver ), + mRotationObserver( NULL ), + mDragAndDropDetector( dndDetector ), + mAccessibilityAdaptor( AccessibilityAdaptor::Get() ), + mClipboardEventNotifier( ClipboardEventNotifier::Get() ), + mClipboard( Clipboard::Get() ), + mImpl( NULL ), + mPaused( false ) +{ + Ecore_Wl2_Window* window = 0; + + // this code only works with the Ecore RenderSurface so need to downcast + ECore::WindowRenderSurface* ecoreSurface = dynamic_cast< ECore::WindowRenderSurface* >( surface ); + if( ecoreSurface ) + { + window = ecoreSurface->GetWlWindow(); + } + + mImpl = new Impl(this, window); +} + +EventHandler::~EventHandler() +{ + if(mImpl) + { + delete mImpl; + } + + mGestureManager.Stop(); +} + +void EventHandler::SendEvent(Integration::Point& point, unsigned long timeStamp) +{ + if(timeStamp < 1) + { + timeStamp = GetCurrentMilliSeconds(); + } + + mImpl->ConvertTouchPosition( point ); + + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent); + if(type != Integration::TouchEventCombiner::DispatchNone ) + { + DALI_LOG_INFO(gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetScreenPosition().x, point.GetScreenPosition().y); + + // First the touch and/or hover event & related gesture events are queued + if(type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth) + { + mCoreEventInterface.QueueCoreEvent( touchEvent ); + mGestureManager.SendEvent(touchEvent); + } + + if(type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth) + { + mCoreEventInterface.QueueCoreEvent( hoverEvent ); + } + + // Next the events are processed with a single call into Core + mCoreEventInterface.ProcessCoreEvents(); + } +} + +void EventHandler::SendEvent(Integration::KeyEvent& keyEvent) +{ + Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get(); + if ( physicalKeyboard ) + { + if ( ! KeyLookup::IsDeviceButton( keyEvent.keyName.c_str() ) ) + { + GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 ); + } + } + + // Create send KeyEvent to Core. + mCoreEventInterface.QueueCoreEvent( keyEvent ); + mCoreEventInterface.ProcessCoreEvents(); +} + +void EventHandler::SendWheelEvent( WheelEvent& wheelEvent ) +{ + // Create WheelEvent and send to Core. + Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp ); + mCoreEventInterface.QueueCoreEvent( event ); + mCoreEventInterface.ProcessCoreEvents(); +} + +void EventHandler::SendEvent( StyleChange::Type styleChange ) +{ + DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" ); + GetImplementation( mStyleMonitor ).StyleChanged(styleChange); +} + +void EventHandler::SendEvent( const DamageArea& area ) +{ + mDamageObserver.OnDamaged( area ); +} + +void EventHandler::SendRotationPrepareEvent( const RotationEvent& event ) +{ + if( mRotationObserver != NULL ) + { + mImpl->mRotationAngle = event.angle; + mImpl->mWindowWidth = event.width; + mImpl->mWindowHeight = event.height; + + mRotationObserver->OnRotationPrepare( event ); + mRotationObserver->OnRotationRequest(); + } +} + +void EventHandler::SendRotationRequestEvent( ) +{ + // No need to separate event into prepare and request in wayland +} + +void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp) +{ + Integration::Point convertedPoint( point ); + SendEvent(convertedPoint, timeStamp); +} + +void EventHandler::FeedWheelEvent( WheelEvent& wheelEvent ) +{ + SendWheelEvent( wheelEvent ); +} + +void EventHandler::FeedKeyEvent( KeyEvent& event ) +{ + Integration::KeyEvent convertedEvent( event ); + SendEvent( convertedEvent ); +} + +void EventHandler::FeedEvent( Integration::Event& event ) +{ + mCoreEventInterface.QueueCoreEvent( event ); + mCoreEventInterface.ProcessCoreEvents(); +} + +void EventHandler::Reset() +{ + mCombiner.Reset(); + + // Any touch listeners should be told of the interruption. + Integration::TouchEvent event; + Integration::Point point; + point.SetState( PointState::INTERRUPTED ); + event.AddPoint( point ); + + // First the touch event & related gesture events are queued + mCoreEventInterface.QueueCoreEvent( event ); + mGestureManager.SendEvent( event ); + + // Next the events are processed with a single call into Core + mCoreEventInterface.ProcessCoreEvents(); +} + +void EventHandler::Pause() +{ + mPaused = true; + Reset(); +} + +void EventHandler::Resume() +{ + mPaused = false; + Reset(); +} + +void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector ) +{ + mDragAndDropDetector = detector; +} + +void EventHandler::SetRotationObserver( RotationObserver* observer ) +{ + mRotationObserver = observer; +} + +} // namespace Adaptor + +} // namespace Internal + +} // namespace Dali + +#pragma GCC diagnostic pop diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/pixmap-render-surface-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/pixmap-render-surface-ecore-wl2.cpp new file mode 100644 index 0000000..65eb070 --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/pixmap-render-surface-ecore-wl2.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2014 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 + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +#if defined(DEBUG_ENABLED) +extern Debug::Filter* gRenderSurfaceLogFilter; +#endif + +namespace ECore +{ + +PixmapRenderSurface::PixmapRenderSurface(Dali::PositionSize positionSize, + Any surface, + const std::string& name, + bool isTransparent) +: EcoreWlRenderSurface( positionSize, surface, name, isTransparent ) +{ + Init( surface ); +} + +PixmapRenderSurface::~PixmapRenderSurface() +{ + // release the surface if we own one + if( mOwnSurface ) + { + //TODO: if we did create the pixmap, delete the pixmap + } +} + +Ecore_Wl2_Window* PixmapRenderSurface::GetDrawable() +{ + return NULL; +} + +Any PixmapRenderSurface::GetSurface() +{ + return Any( NULL ); +} + +void PixmapRenderSurface::InitializeEgl( EglInterface& egl ) +{ + DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); + + Internal::Adaptor::EglImplementation& eglImpl = static_cast( egl ); + + eglImpl.ChooseConfig(false, mColorDepth); +} + +void PixmapRenderSurface::CreateEglSurface( EglInterface& egl ) +{ + DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); + + // create the EGL surface + // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit + // FIXME +} + +void PixmapRenderSurface::DestroyEglSurface( EglInterface& egl ) +{ + DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); + + Internal::Adaptor::EglImplementation& eglImpl = static_cast( egl ); + eglImpl.DestroySurface(); +} + +bool PixmapRenderSurface::ReplaceEGLSurface( EglInterface& egl ) +{ + DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); + + // a new surface for the new pixmap + // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit + // FIXME + return false; +} + +void PixmapRenderSurface::StartRender() +{ + // FIXME +} + +bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&, bool ) +{ + // nothing to do for pixmaps + return true; +} + +void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface ) +{ + // flush gl instruction queue + glAbstraction.Flush(); + + // create damage for client applications which wish to know the update timing + if( mRenderNotification ) + { + // use notification trigger + // Tell the event-thread to render the pixmap + mRenderNotification->Trigger(); + } + else + { + // FIXME + } + + // Do render synchronisation + // AcquireLock( replacingSurface ? SYNC_MODE_NONE : SYNC_MODE_WAIT ); +} + +void PixmapRenderSurface::StopRender() +{ + // FIXME +} + +void PixmapRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization ) +{ + // Nothing to do +} + +void PixmapRenderSurface::CreateWlRenderable() +{ + // check we're creating one with a valid size + DALI_ASSERT_ALWAYS( mPositionSize.width > 0 && mPositionSize.height > 0 && "Pixmap size is invalid" ); + + // FIXME +} + +void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId ) +{ + // FIXME +} + +void PixmapRenderSurface::SetSyncMode( SyncMode syncMode ) +{ + // FIXME +} + +void PixmapRenderSurface::AcquireLock() +{ + // FIXME +} + +void PixmapRenderSurface::ReleaseLock() +{ + // FIXME +} + +} // namespace ECore + +} // namespace Dali diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/render-surface-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/render-surface-ecore-wl2.cpp new file mode 100644 index 0000000..37a32dc --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/render-surface-ecore-wl2.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2017 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 + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +#if defined(DEBUG_ENABLED) +Debug::Filter* gRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_ECORE_WL_RENDER_SURFACE"); +#endif + +namespace ECore +{ + +EcoreWlRenderSurface::EcoreWlRenderSurface(Dali::PositionSize positionSize, + Any surface, + const std::string& name, + bool isTransparent) +: mPositionSize( positionSize ), + mTitle( name ), + mRenderNotification( NULL ), + mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ), + mOwnSurface( false ) +{ +} + +void EcoreWlRenderSurface::Init( Any surface ) +{ + // see if there is a surface in Any surface + unsigned int surfaceId = GetSurfaceId( surface ); + + // if the surface is empty, create a new one. + if ( surfaceId == 0 ) + { + // we own the surface about to created + ecore_wl2_init(); + mOwnSurface = true; + CreateWlRenderable(); + } + else + { + // XLib should already be initialized so no point in calling XInitThreads + UseExistingRenderable( surfaceId ); + } + +#ifdef DEBUG_ENABLED + // prints out 'INFO: DALI: new EcoreWlRenderSurface, created display xx, used existing surface xx + // we can not use LOG_INFO because the surface can be created before Dali Core is created. + // TODO: Overy tizen 3.0, we don't use X anymore. Change this for Tizen 3.0 + /* + printf( "INFO: DALI: new EcoreWlRenderSurface, %s %s surface %X \n", + mOwnSurface?"created":"used existing", + Dali::RenderSurface::PIXMAP==mType?" pixmap" :"window", + AnyCast( GetSurface() ) ); + */ +#endif +} + +EcoreWlRenderSurface::~EcoreWlRenderSurface() +{ + if( mOwnSurface ) + { + ecore_wl2_shutdown(); + } +} + +void EcoreWlRenderSurface::SetRenderNotification(TriggerEventInterface* renderNotification) +{ + mRenderNotification = renderNotification; +} + +Ecore_Wl2_Window* EcoreWlRenderSurface::GetWlWindow() +{ + return 0; +} + +Ecore_Wl2_Window* EcoreWlRenderSurface::GetDrawable() +{ + return 0; +} + +PositionSize EcoreWlRenderSurface::GetPositionSize() const +{ + return mPositionSize; +} + +void EcoreWlRenderSurface::MoveResize( Dali::PositionSize positionSize ) +{ + // nothing to do in base class +} + +void EcoreWlRenderSurface::SetViewMode( ViewMode viewMode ) +{ +} + +unsigned int EcoreWlRenderSurface::GetSurfaceId( Any surface ) const +{ + unsigned int surfaceId = 0; + + if ( surface.Empty() == false ) + { + // check we have a valid type + DALI_ASSERT_ALWAYS( ( (surface.GetType() == typeid (Ecore_Wl2_Window *) ) ) + && "Surface type is invalid" ); + + surfaceId = AnyCast( surface ); + } + return surfaceId; +} + +RenderSurface::Type EcoreWlRenderSurface::GetSurfaceType() +{ + return RenderSurface::ECORE_RENDER_SURFACE; +} + +} // namespace ECore + +} // namespace Dali diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-impl-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-impl-ecore-wl2.cpp new file mode 100644 index 0000000..4c68f02 --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-impl-ecore-wl2.cpp @@ -0,0 +1,1569 @@ +/* + * Copyright (c) 2017 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 + +// EXTERNAL HEADERS +// Ecore is littered with C style cast +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include +#include +#include + +#include +#include +#include +#include +#include + +// INTERNAL HEADERS +#include +#include +#include +#include +#include + +namespace +{ + +const float INDICATOR_ANIMATION_DURATION( 0.18f ); // 180 milli seconds +const float INDICATOR_SHOW_Y_POSITION( 0.0f ); +const float INDICATOR_HIDE_Y_POSITION( -52.0f ); + +const uint32_t MAX_TIZEN_CLIENT_VERSION = 7; + +} + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ + +#if defined(DEBUG_ENABLED) +Debug::Filter* gWindowLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_WINDOW"); +#endif + +/** + * TODO: Abstract Window class out and move this into a window implementation for Ecore + */ +struct Window::EventHandler +{ + /** + * Constructor + * @param[in] window A pointer to the window class. + */ + EventHandler( Window* window ) + : mWindow( window ), + mEcoreEventHandler(), + mEcoreWindow( 0 ), + mDisplay( NULL ), + mEventQueue( NULL ), + mTizenPolicy( NULL ), + mTizenDisplayPolicy( NULL ), + mNotificationLevel( -1 ), + mNotificationChangeState( 0 ), + mNotificationLevelChangeDone( true ), + mScreenOffMode( 0 ), + mScreenOffModeChangeState( 0 ), + mScreenOffModeChangeDone( true ), + mBrightness( 0 ), + mBrightnessChangeState( 0 ), + mBrightnessChangeDone( true ) + { + // store ecore window handle + ECore::WindowRenderSurface* wlWindow( dynamic_cast< ECore::WindowRenderSurface * >( mWindow->mSurface ) ); + if( wlWindow ) + { + mEcoreWindow = wlWindow->GetWlWindow(); + } + DALI_ASSERT_ALWAYS( mEcoreWindow != 0 && "There is no ecore Wl window"); + + if( mWindow->mEcoreEventHander ) + { + mEcoreEventHandler.PushBack( ecore_event_handler_add( ECORE_WL2_EVENT_WINDOW_ICONIFY_STATE_CHANGE, EcoreEventWindowIconifyStateChanged, this ) ); + mEcoreEventHandler.PushBack( ecore_event_handler_add( ECORE_WL2_EVENT_FOCUS_IN, EcoreEventWindowFocusIn, this ) ); + mEcoreEventHandler.PushBack( ecore_event_handler_add( ECORE_WL2_EVENT_FOCUS_OUT, EcoreEventWindowFocusOut, this ) ); + mEcoreEventHandler.PushBack( ecore_event_handler_add( ECORE_WL2_EVENT_OUTPUT_TRANSFORM, EcoreEventOutputTransform, this) ); + mEcoreEventHandler.PushBack( ecore_event_handler_add( ECORE_WL2_EVENT_IGNORE_OUTPUT_TRANSFORM, EcoreEventIgnoreOutputTransform, this) ); + } + + Ecore_Wl2_Display *ecore_wl2_display = ecore_wl2_connected_display_get(NULL); + mDisplay = ecore_wl2_display_get(ecore_wl2_display); + + if( mDisplay ) + { + wl_display* displayWrapper = static_cast< wl_display* >( wl_proxy_create_wrapper( mDisplay ) ); + if( displayWrapper ) + { + mEventQueue = wl_display_create_queue( mDisplay ); + if( mEventQueue ) + { + wl_proxy_set_queue( reinterpret_cast< wl_proxy* >( displayWrapper ), mEventQueue ); + + wl_registry* registry = wl_display_get_registry( displayWrapper ); + wl_registry_add_listener( registry, &mRegistryListener, this ); + } + + wl_proxy_wrapper_destroy( displayWrapper ); + } + } + } + + /** + * Destructor + */ + ~EventHandler() + { + for( Dali::Vector< Ecore_Event_Handler* >::Iterator iter = mEcoreEventHandler.Begin(), endIter = mEcoreEventHandler.End(); iter != endIter; ++iter ) + { + ecore_event_handler_del( *iter ); + } + mEcoreEventHandler.Clear(); + + if( mEventQueue ) + { + wl_event_queue_destroy( mEventQueue ); + } + } + + // Static methods + + /// Called when the window iconify state is changed. + static Eina_Bool EcoreEventWindowIconifyStateChanged( void* data, int type, void* event ) + { + Ecore_Wl2_Event_Window_Iconify_State_Change* iconifyChangedEvent( static_cast< Ecore_Wl2_Event_Window_Iconify_State_Change* >( event ) ); + EventHandler* handler( static_cast< EventHandler* >( data ) ); + Eina_Bool handled( ECORE_CALLBACK_PASS_ON ); + + if ( handler && handler->mWindow ) + { + WindowVisibilityObserver* observer( handler->mWindow->mAdaptor ); + if ( observer && ( iconifyChangedEvent->win == static_cast< unsigned int> ( ecore_wl2_window_id_get( handler->mEcoreWindow ) ) ) ) + { + if( iconifyChangedEvent->iconified == EINA_TRUE ) + { + handler->mWindow->mIconified = true; + if( handler->mWindow->mVisible ) + { + observer->OnWindowHidden(); + } + DALI_LOG_RELEASE_INFO( "Window (%p) Iconified\n", handler->mEcoreWindow); + } + else + { + handler->mWindow->mIconified = false; + if( handler->mWindow->mVisible ) + { + observer->OnWindowShown(); + } + DALI_LOG_RELEASE_INFO( "Window (%p) Deiconified\n", handler->mEcoreWindow ); + } + handled = ECORE_CALLBACK_DONE; + } + } + + return handled; + } + + /// Called when the window gains focus + static Eina_Bool EcoreEventWindowFocusIn( void* data, int type, void* event ) + { + Ecore_Wl2_Event_Focus_In* focusInEvent( static_cast< Ecore_Wl2_Event_Focus_In* >( event ) ); + EventHandler* handler( static_cast< EventHandler* >( data ) ); + + if ( handler && handler->mWindow && focusInEvent->window == static_cast< unsigned int >( ecore_wl2_window_id_get( handler->mEcoreWindow ) ) ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window EcoreEventWindowFocusIn\n" ); + + handler->mWindow->mFocusChangedSignal.Emit( true ); + } + + return ECORE_CALLBACK_PASS_ON; + } + + /// Called when the window loses focus + static Eina_Bool EcoreEventWindowFocusOut( void* data, int type, void* event ) + { + Ecore_Wl2_Event_Focus_Out* focusOutEvent( static_cast< Ecore_Wl2_Event_Focus_Out* >( event ) ); + EventHandler* handler( static_cast< EventHandler* >( data ) ); + + if ( handler && handler->mWindow && focusOutEvent->window == static_cast< unsigned int >(ecore_wl2_window_id_get( handler->mEcoreWindow ) ) ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window EcoreEventWindowFocusOut\n" ); + + handler->mWindow->mFocusChangedSignal.Emit( false ); + } + + return ECORE_CALLBACK_PASS_ON; + } + + /// Called when the output is transformed + static Eina_Bool EcoreEventOutputTransform( void* data, int type, void* event ) + { + Ecore_Wl2_Event_Output_Transform* transformEvent( static_cast< Ecore_Wl2_Event_Output_Transform* >( event ) ); + EventHandler* handler( static_cast< EventHandler* >( data ) ); + + if ( handler && handler->mWindow && transformEvent->output == ecore_wl2_window_output_find( handler->mEcoreWindow ) ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%p) EcoreEventOutputTransform\n", handler->mEcoreWindow ); + + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( handler->mWindow->mSurface ) ); + if( wlSurface ) + { + wlSurface->OutputTransformed(); + + PositionSize positionSize = wlSurface->GetPositionSize(); + handler->mWindow->mAdaptor->SurfaceResizePrepare( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) ); + handler->mWindow->mAdaptor->SurfaceResizeComplete( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) ); + } + } + + return ECORE_CALLBACK_PASS_ON; + } + + /// Called when the output transform should be ignored + static Eina_Bool EcoreEventIgnoreOutputTransform( void* data, int type, void* event ) + { + Ecore_Wl2_Event_Ignore_Output_Transform* ignoreTransformEvent( static_cast< Ecore_Wl2_Event_Ignore_Output_Transform* >( event ) ); + EventHandler* handler( static_cast< EventHandler* >( data ) ); + + if ( handler && handler->mWindow && ignoreTransformEvent->win == handler->mEcoreWindow ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%p) EcoreEventIgnoreOutputTransform\n", handler->mEcoreWindow ); + + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( handler->mWindow->mSurface ) ); + if( wlSurface ) + { + wlSurface->OutputTransformed(); + + PositionSize positionSize = wlSurface->GetPositionSize(); + handler->mWindow->mAdaptor->SurfaceResizePrepare( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) ); + handler->mWindow->mAdaptor->SurfaceResizeComplete( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) ); + } + } + + return ECORE_CALLBACK_PASS_ON; + } + + static void RegistryGlobalCallback( void* data, struct wl_registry *registry, uint32_t name, const char* interface, uint32_t version ) + { + Window::EventHandler* eventHandler = static_cast< Window::EventHandler* >( data ); + + if( strcmp( interface, tizen_policy_interface.name ) == 0 ) + { + uint32_t clientVersion = std::min( version, MAX_TIZEN_CLIENT_VERSION ); + + eventHandler->mTizenPolicy = static_cast< tizen_policy* >( wl_registry_bind( registry, name, &tizen_policy_interface, clientVersion ) ); + if( !eventHandler->mTizenPolicy ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window::EventHandler::RegistryGlobalCallback: wl_registry_bind(tizen_policy_interface) is failed.\n" ); + return; + } + + tizen_policy_add_listener( eventHandler->mTizenPolicy, &eventHandler->mTizenPolicyListener, data ); + + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window::EventHandler::RegistryGlobalCallback: tizen_policy_add_listener is called.\n" ); + } + else if( strcmp( interface, tizen_display_policy_interface.name ) == 0 ) + { + eventHandler->mTizenDisplayPolicy = static_cast< tizen_display_policy* >( wl_registry_bind( registry, name, &tizen_display_policy_interface, version ) ); + if( !eventHandler->mTizenDisplayPolicy ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window::EventHandler::RegistryGlobalCallback: wl_registry_bind(tizen_display_policy_interface) is failed.\n" ); + return; + } + + tizen_display_policy_add_listener( eventHandler->mTizenDisplayPolicy, &eventHandler->mTizenDisplayPolicyListener, data ); + + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window::EventHandler::RegistryGlobalCallback: tizen_display_policy_add_listener is called.\n" ); + } + } + + static void RegistryGlobalCallbackRemove( void* data, struct wl_registry* registry, uint32_t id ) + { + Window::EventHandler* eventHandler = static_cast< Window::EventHandler* >( data ); + eventHandler->mTizenPolicy = NULL; + eventHandler->mTizenDisplayPolicy = NULL; + } + + static void TizenPolicyConformant( void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, uint32_t isConformant ) + { + } + + static void TizenPolicyConformantArea( void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, uint32_t conformantPart, uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h ) + { + } + + static void TizenPolicyNotificationChangeDone(void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, int32_t level, uint32_t state ) + { + Window::EventHandler* eventHandler = static_cast< Window::EventHandler* >( data ); + + eventHandler->mNotificationLevel = level; + eventHandler->mNotificationChangeState = state; + eventHandler->mNotificationLevelChangeDone = true; + + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window::EventHandler::TizenPolicyNotificationChangeDone: level = %d, state = %d\n", level, state ); + } + + static void TizenPolicyTransientForDone( void* data, struct tizen_policy* tizenPolicy, uint32_t childId ) + { + } + + static void TizenPolicyScreenModeChangeDone( void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, uint32_t mode, uint32_t state ) + { + Window::EventHandler* eventHandler = static_cast< Window::EventHandler* >( data ); + + eventHandler->mScreenOffMode = mode; + eventHandler->mScreenOffModeChangeState = state; + eventHandler->mScreenOffModeChangeDone = true; + + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window::EventHandler::TizenPolicyScreenModeChangeDone: mode = %d, state = %d\n", mode, state ); + } + + static void TizenPolicyIconifyStateChanged( void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, uint32_t iconified, uint32_t force ) + { + } + + static void TizenPolicySupportedAuxiliaryHints( void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, struct wl_array* hints, uint32_t numNints ) + { + } + + static void TizenPolicyAllowedAuxiliaryHint( void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, int id ) + { + } + + static void TizenPolicyAuxiliaryMessage( void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, const char* key, const char* val, struct wl_array* options ) + { + } + + static void TizenPolicyConformantRegion( void* data, struct tizen_policy* tizenPolicy, struct wl_surface* surface, uint32_t conformantPart, uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t serial ) + { + } + + static void DisplayPolicyBrightnessChangeDone( void* data, struct tizen_display_policy *displayPolicy, struct wl_surface* surface, int32_t brightness, uint32_t state ) + { + Window::EventHandler* eventHandler = static_cast< Window::EventHandler* >( data ); + + eventHandler->mBrightness = brightness; + eventHandler->mBrightnessChangeState = state; + eventHandler->mBrightnessChangeDone = true; + + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window::EventHandler::DisplayPolicyBrightnessChangeDone: brightness = %d, state = %d\n", brightness, state ); + } + + const struct wl_registry_listener mRegistryListener = + { + RegistryGlobalCallback, + RegistryGlobalCallbackRemove + }; + + const struct tizen_policy_listener mTizenPolicyListener = + { + TizenPolicyConformant, + TizenPolicyConformantArea, + TizenPolicyNotificationChangeDone, + TizenPolicyTransientForDone, + TizenPolicyScreenModeChangeDone, + TizenPolicyIconifyStateChanged, + TizenPolicySupportedAuxiliaryHints, + TizenPolicyAllowedAuxiliaryHint, + TizenPolicyAuxiliaryMessage, + TizenPolicyConformantRegion + }; + + const struct tizen_display_policy_listener mTizenDisplayPolicyListener = + { + DisplayPolicyBrightnessChangeDone + }; + + // Data + Window* mWindow; + Dali::Vector< Ecore_Event_Handler* > mEcoreEventHandler; + Ecore_Wl2_Window* mEcoreWindow; + + wl_display* mDisplay; + wl_event_queue* mEventQueue; + tizen_policy* mTizenPolicy; + tizen_display_policy* mTizenDisplayPolicy; + + int mNotificationLevel; + uint32_t mNotificationChangeState; + bool mNotificationLevelChangeDone; + + int mScreenOffMode; + uint32_t mScreenOffModeChangeState; + bool mScreenOffModeChangeDone; + + int mBrightness; + uint32_t mBrightnessChangeState; + bool mBrightnessChangeDone; +}; + +Window* Window::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent ) +{ + Window* window = new Window(); + window->mIsTransparent = isTransparent; + window->Initialize( positionSize, name, className ); + return window; +} + +void Window::SetAdaptor(Dali::Adaptor& adaptor) +{ + DALI_ASSERT_ALWAYS( !mStarted && "Adaptor already started" ); + mStarted = true; + + // Only create one overlay per window + Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation(adaptor); + Integration::Core& core = adaptorImpl.GetCore(); + mOverlay = &core.GetSystemOverlay(); + + Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks(); + taskList.CreateTask(); + + mAdaptor = &adaptorImpl; + mAdaptor->AddObserver( *this ); + + // Can only create the detector when we know the Core has been instantiated. + mDragAndDropDetector = DragAndDropDetector::New(); + mAdaptor->SetDragAndDropDetector( &GetImplementation( mDragAndDropDetector ) ); + + if( mOrientation ) + { + mOrientation->SetAdaptor(adaptor); + } + + if( mIndicator != NULL ) + { + mIndicator->SetAdaptor(mAdaptor); + } +} + +RenderSurface* Window::GetSurface() +{ + return mSurface; +} + +void Window::ShowIndicator( Dali::Window::IndicatorVisibleMode visibleMode ) +{ + DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "visible : %d\n", visibleMode ); + DALI_ASSERT_DEBUG(mOverlay); + + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) ); + DALI_ASSERT_DEBUG(wlSurface); + + if( wlSurface ) + { + Ecore_Wl2_Window* wlWindow = wlSurface->GetWlWindow(); + + mIndicatorVisible = visibleMode; + + if ( mIndicatorVisible == Dali::Window::VISIBLE ) + { + // when the indicator is visible, set proper mode for indicator server according to bg mode + if ( mIndicatorOpacityMode == Dali::Window::OPAQUE ) + { + ecore_wl2_window_indicator_opacity_set(wlWindow, ECORE_WL2_INDICATOR_OPAQUE); + } + else if ( mIndicatorOpacityMode == Dali::Window::TRANSLUCENT ) + { + ecore_wl2_window_indicator_opacity_set(wlWindow, ECORE_WL2_INDICATOR_TRANSLUCENT); + } + else if ( mIndicatorOpacityMode == Dali::Window::TRANSPARENT ) + { + ecore_wl2_window_indicator_opacity_set(wlWindow, ECORE_WL2_INDICATOR_OPAQUE); + } + } + else + { + // when the indicator is not visible, set TRANSPARENT mode for indicator server + ecore_wl2_window_indicator_opacity_set(wlWindow, ECORE_WL2_INDICATOR_TRANSPARENT); // it means hidden indicator + } + } + + DoShowIndicator( mIndicatorOrientation ); +} + +void Window::RotateIndicator( Dali::Window::WindowOrientation orientation ) +{ + DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "Orientation: %d\n", orientation ); + + DoRotateIndicator( orientation ); +} + +void Window::SetIndicatorBgOpacity( Dali::Window::IndicatorBgOpacity opacityMode ) +{ + mIndicatorOpacityMode = opacityMode; + + if( mIndicator != NULL ) + { + mIndicator->SetOpacityMode( opacityMode ); + } +} + +void Window::SetClass(std::string name, std::string klass) +{ + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) ); + + if( wlSurface ) + { + Ecore_Wl2_Window* wlWindow = wlSurface->GetWlWindow(); + ecore_wl2_window_title_set( wlWindow, name.c_str() ); + ecore_wl2_window_class_set( wlWindow, klass.c_str() ); + } + else + { + DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window has no surface\n" ); + } +} + +Window::Window() +: mSurface( NULL ), + mIndicatorVisible( Dali::Window::VISIBLE ), + mIndicatorIsShown( false ), + mShowRotatedIndicatorOnClose( false ), + mStarted( false ), + mIsTransparent( false ), + mWMRotationAppSet( false ), + mEcoreEventHander( true ), + mIsFocusAcceptable( true ), + mVisible( true ), + mIconified( false ), + mOpaqueState( false ), + mResizeEnabled( false ), + mIndicator( NULL ), + mIndicatorOrientation( Dali::Window::PORTRAIT ), + mNextIndicatorOrientation( Dali::Window::PORTRAIT ), + mIndicatorOpacityMode( Dali::Window::OPAQUE ), + mOverlay( NULL ), + mAdaptor( NULL ), + mType( Dali::Window::NORMAL ), + mEventHandler( NULL ), + mPreferredOrientation( Dali::Window::PORTRAIT ), + mSupportedAuxiliaryHints(), + mAuxiliaryHints(), + mIndicatorVisibilityChangedSignal(), + mFocusChangedSignal(), + mResizedSignal(), + mDeleteRequestSignal() +{ +} + +Window::~Window() +{ + delete mEventHandler; + + if( mIndicator ) + { + mIndicator->Close(); + delete mIndicator; + } + + if ( mAdaptor ) + { + mAdaptor->RemoveObserver( *this ); + mAdaptor->SetDragAndDropDetector( NULL ); + mAdaptor = NULL; + } + + delete mSurface; + + mSupportedAuxiliaryHints.clear(); + mAuxiliaryHints.clear(); +} + +void Window::Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className) +{ + // create an Wayland window by default + Any surface; + ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( positionSize, surface, name, mIsTransparent ); + + mSurface = windowSurface; + + // create event handler for Wayland window + mEventHandler = new EventHandler( this ); + + // get auxiliary hint + Eina_List* hints = ecore_wl2_window_aux_hints_supported_get( mEventHandler->mEcoreWindow ); + if( hints ) + { + Eina_List* l = NULL; + char* hint = NULL; + + for( l = hints, ( hint = static_cast< char* >( eina_list_data_get(l) ) ); l; l = eina_list_next(l), ( hint = static_cast< char* >( eina_list_data_get(l) ) ) ) + { + mSupportedAuxiliaryHints.push_back( hint ); + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::Initialize: %s\n", hint ); + } + } + + if( !positionSize.IsEmpty() ) + { + AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" ); + mResizeEnabled = true; + } + + SetClass( name, className ); + windowSurface->Map(); + + mOrientation = Orientation::New(this); +} + +void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation ) +{ + if( mIndicator == NULL ) + { + if( mIndicatorVisible != Dali::Window::INVISIBLE ) + { + mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this ); + mIndicator->SetOpacityMode( mIndicatorOpacityMode ); + Dali::Actor actor = mIndicator->GetActor(); + SetIndicatorActorRotation(); + mOverlay->Add(actor); + } + // else don't create a hidden indicator + } + else // Already have indicator + { + if( mIndicatorVisible == Dali::Window::VISIBLE ) + { + // If we are resuming, and rotation has changed, + if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation ) + { + // then close current indicator and open new one + mShowRotatedIndicatorOnClose = true; + mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion + // Don't show actor - will contain indicator for old orientation. + } + } + } + + // set indicator visible mode + if( mIndicator != NULL ) + { + mIndicator->SetVisible( mIndicatorVisible ); + } + + bool show = (mIndicatorVisible != Dali::Window::INVISIBLE ); + SetIndicatorProperties( show, lastOrientation ); + mIndicatorIsShown = show; +} + +void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation ) +{ + if( mIndicatorIsShown ) + { + mShowRotatedIndicatorOnClose = true; + mNextIndicatorOrientation = orientation; + mIndicator->Close(); // May synchronously call IndicatorClosed() callback + } + else + { + // Save orientation for when the indicator is next shown + mShowRotatedIndicatorOnClose = false; + mNextIndicatorOrientation = orientation; + } +} + +void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation ) +{ + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) ); + + if( wlSurface ) + { + Ecore_Wl2_Window* wlWindow = wlSurface->GetWlWindow(); + if ( isShow ) + { + ecore_wl2_window_indicator_state_set(wlWindow, ECORE_WL2_INDICATOR_STATE_ON); + } + else + { + ecore_wl2_window_indicator_state_set(wlWindow, ECORE_WL2_INDICATOR_STATE_OFF); + } + } +} + +void Window::IndicatorTypeChanged(Indicator::Type type) +{ +#if defined(DALI_PROFILE_MOBILE) + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) ); + + if( wlSurface ) + { + Ecore_Wl2_Window* wlWindow = wlSurface->GetWlWindow(); + switch(type) + { + case Indicator::INDICATOR_TYPE_1: + ecore_wl2_indicator_visible_type_set(wlWindow, ECORE_WL2_INDICATOR_VISIBLE_TYPE_SHOWN); + break; + + case Indicator::INDICATOR_TYPE_2: + ecore_wl2_indicator_visible_type_set(wlWindow, ECORE_WL2_INDICATOR_VISIBLE_TYPE_HIDDEN); + break; + + case Indicator::INDICATOR_TYPE_UNKNOWN: + default: + break; + } + } +#endif //MOBILE +} + +void Window::IndicatorClosed( IndicatorInterface* indicator ) +{ + DALI_LOG_TRACE_METHOD( gWindowLogFilter ); + + if( mShowRotatedIndicatorOnClose ) + { + Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation; + mIndicator->Open(mNextIndicatorOrientation); + mIndicatorOrientation = mNextIndicatorOrientation; + SetIndicatorActorRotation(); + DoShowIndicator(currentOrientation); + } +} + +void Window::IndicatorVisibilityChanged(bool isVisible) +{ + mIndicatorVisibilityChangedSignal.Emit(isVisible); +} + +void Window::SetIndicatorActorRotation() +{ + DALI_LOG_TRACE_METHOD( gWindowLogFilter ); + DALI_ASSERT_DEBUG( mIndicator != NULL ); + + Dali::Actor actor = mIndicator->GetActor(); + switch( mIndicatorOrientation ) + { + case Dali::Window::PORTRAIT: + actor.SetParentOrigin( ParentOrigin::TOP_CENTER ); + actor.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + actor.SetOrientation( Degree(0), Vector3::ZAXIS ); + break; + case Dali::Window::PORTRAIT_INVERSE: + actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); + actor.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + actor.SetOrientation( Degree(180), Vector3::ZAXIS ); + break; + case Dali::Window::LANDSCAPE: + actor.SetParentOrigin( ParentOrigin::CENTER_LEFT ); + actor.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + actor.SetOrientation( Degree(270), Vector3::ZAXIS ); + break; + case Dali::Window::LANDSCAPE_INVERSE: + actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT ); + actor.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + actor.SetOrientation( Degree(90), Vector3::ZAXIS ); + break; + } +} + +void Window::Raise() +{ + // Use ecore_wl2_window_activate to prevent the window shown without rendering + ecore_wl2_window_activate( mEventHandler->mEcoreWindow ); +} + +void Window::Lower() +{ + ecore_wl2_window_lower( mEventHandler->mEcoreWindow ); +} + +void Window::Activate() +{ + ecore_wl2_window_activate( mEventHandler->mEcoreWindow ); +} + +Dali::DragAndDropDetector Window::GetDragAndDropDetector() const +{ + return mDragAndDropDetector; +} + +Dali::Any Window::GetNativeHandle() const +{ + if(mEventHandler) + { + return mEventHandler->mEcoreWindow; + } + else + { + return Dali::Any(); + } +} + +void Window::OnStart() +{ + DoShowIndicator( mIndicatorOrientation ); +} + +void Window::OnPause() +{ +} + +void Window::OnResume() +{ + // resume indicator status + if( mIndicator != NULL ) + { + // Restore own indicator opacity + // Send opacity mode to indicator service when app resumed + mIndicator->SetOpacityMode( mIndicatorOpacityMode ); + } +} + +void Window::OnStop() +{ + if( mIndicator ) + { + mIndicator->Close(); + } + + delete mIndicator; + mIndicator = NULL; +} + +void Window::OnDestroy() +{ + mAdaptor = NULL; +} + +void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation) +{ + bool found = false; + + if ( orientation <= Dali::Window::LANDSCAPE_INVERSE ) + { + for( std::size_t i = 0; i < mAvailableOrientations.size(); i++ ) + { + if( mAvailableOrientations[i] == orientation ) + { + found = true; + break; + } + } + + if( ! found ) + { + mAvailableOrientations.push_back(orientation); + SetAvailableOrientations( mAvailableOrientations ); + } + } +} + +void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation) +{ + for( std::vector::iterator iter = mAvailableOrientations.begin(); + iter != mAvailableOrientations.end(); ++iter ) + { + if( *iter == orientation ) + { + mAvailableOrientations.erase( iter ); + break; + } + } + SetAvailableOrientations( mAvailableOrientations ); +} + +void Window::SetAvailableOrientations(const std::vector& orientations) +{ + int rotations[4]; + for( std::size_t i = 0; i < mAvailableOrientations.size(); ++i ) + { + rotations[i] = static_cast< int >( mAvailableOrientations[i] ); + } + ecore_wl2_window_available_rotations_set( mEventHandler->mEcoreWindow, rotations, mAvailableOrientations.size() ); +} + +const std::vector& Window::GetAvailableOrientations() +{ + return mAvailableOrientations; +} + +void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation) +{ + mPreferredOrientation = orientation; + + ecore_wl2_window_preferred_rotation_set( mEventHandler->mEcoreWindow, orientation ); +} + +Dali::Window::WindowOrientation Window::GetPreferredOrientation() +{ + return mPreferredOrientation; +} + +void Window::SetAcceptFocus( bool accept ) +{ + mIsFocusAcceptable = accept; + + ecore_wl2_window_focus_skip_set( mEventHandler->mEcoreWindow, !accept ); +} + +bool Window::IsFocusAcceptable() const +{ + return mIsFocusAcceptable; +} + +void Window::Show() +{ + mVisible = true; + ecore_wl2_window_show( mEventHandler->mEcoreWindow ); + + if( !mIconified ) + { + if( mAdaptor ) + { + WindowVisibilityObserver* observer( mAdaptor ); + observer->OnWindowShown(); + DALI_LOG_RELEASE_INFO( "Window (%p) ::Show() \n", mEventHandler->mEcoreWindow); + } + } +} + +void Window::Hide() +{ + mVisible = false; + ecore_wl2_window_hide( mEventHandler->mEcoreWindow ); + + if( !mIconified ) + { + if( mAdaptor ) + { + WindowVisibilityObserver* observer( mAdaptor ); + observer->OnWindowHidden(); + DALI_LOG_RELEASE_INFO( "Window (%p) ::Hide() \n", mEventHandler->mEcoreWindow); + } + } +} + +bool Window::IsVisible() const +{ + return mVisible; +} + +void Window::RotationDone( int orientation, int width, int height ) +{ + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) ); + if( wlSurface ) + { + wlSurface->RequestRotation( orientation, width, height ); + } + + mAdaptor->SurfaceResizePrepare( Adaptor::SurfaceSize( width, height ) ); + + // Emit signal + mResizedSignal.Emit( Dali::Window::WindowSize( width, height ) ); + + mAdaptor->SurfaceResizeComplete( Adaptor::SurfaceSize( width, height ) ); +} + +void Window::SetIndicatorVisibleMode( Dali::Window::IndicatorVisibleMode mode ) +{ + mIndicatorVisible = mode; +} + +unsigned int Window::GetSupportedAuxiliaryHintCount() const +{ + return mSupportedAuxiliaryHints.size(); +} + +std::string Window::GetSupportedAuxiliaryHint( unsigned int index ) const +{ + if( index >= GetSupportedAuxiliaryHintCount() ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetSupportedAuxiliaryHint: Invalid index! [%d]\n", index ); + } + + return mSupportedAuxiliaryHints[index]; +} + +unsigned int Window::AddAuxiliaryHint( const std::string& hint, const std::string& value ) +{ + bool supported = false; + + // Check if the hint is suppported + for( std::vector< std::string >::iterator iter = mSupportedAuxiliaryHints.begin(); iter != mSupportedAuxiliaryHints.end(); ++iter ) + { + if( *iter == hint ) + { + supported = true; + break; + } + } + + if( !supported ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Concise, "Window::AddAuxiliaryHint: Not supported auxiliary hint [%s]\n", hint.c_str() ); + return 0; + } + + // Check if the hint is already added + for( unsigned int i = 0; i < mAuxiliaryHints.size(); i++ ) + { + if( mAuxiliaryHints[i].first == hint ) + { + // Just change the value + mAuxiliaryHints[i].second = value; + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::AddAuxiliaryHint: Change! hint = %s, value = %s, id = %d\n", hint.c_str(), value.c_str(), i + 1 ); + + return i + 1; // id is index + 1 + } + } + + // Add the hint + mAuxiliaryHints.push_back( std::pair< std::string, std::string >( hint, value ) ); + + unsigned int id = mAuxiliaryHints.size(); + + ecore_wl2_window_aux_hint_add( mEventHandler->mEcoreWindow, static_cast< int >( id ), hint.c_str(), value.c_str() ); + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::AddAuxiliaryHint: hint = %s, value = %s, id = %d\n", hint.c_str(), value.c_str(), id ); + + return id; +} + +bool Window::RemoveAuxiliaryHint( unsigned int id ) +{ + if( id == 0 || id > mAuxiliaryHints.size() ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Concise, "Window::RemoveAuxiliaryHint: Invalid id [%d]\n", id ); + return false; + } + + mAuxiliaryHints[id - 1].second = std::string(); + + ecore_wl2_window_aux_hint_del( mEventHandler->mEcoreWindow, static_cast< int >( id ) ); + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::RemoveAuxiliaryHint: id = %d, hint = %s\n", id, mAuxiliaryHints[id - 1].first.c_str() ); + + return true; +} + +bool Window::SetAuxiliaryHintValue( unsigned int id, const std::string& value ) +{ + if( id == 0 || id > mAuxiliaryHints.size() ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Concise, "Window::SetAuxiliaryHintValue: Invalid id [%d]\n", id ); + return false; + } + + mAuxiliaryHints[id - 1].second = value; + + ecore_wl2_window_aux_hint_change( mEventHandler->mEcoreWindow, static_cast< int >( id ), value.c_str() ); + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetAuxiliaryHintValue: id = %d, hint = %s, value = %s\n", id, mAuxiliaryHints[id - 1].first.c_str(), mAuxiliaryHints[id - 1].second.c_str() ); + + return true; +} + +std::string Window::GetAuxiliaryHintValue( unsigned int id ) const +{ + if( id == 0 || id > mAuxiliaryHints.size() ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Concise, "Window::GetAuxiliaryHintValue: Invalid id [%d]\n", id ); + return std::string(); + } + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetAuxiliaryHintValue: id = %d, hint = %s, value = %s\n", id, mAuxiliaryHints[id - 1].first.c_str(), mAuxiliaryHints[id - 1].second.c_str() ); + + return mAuxiliaryHints[id - 1].second; +} + +unsigned int Window::GetAuxiliaryHintId( const std::string& hint ) const +{ + for( unsigned int i = 0; i < mAuxiliaryHints.size(); i++ ) + { + if( mAuxiliaryHints[i].first == hint ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetAuxiliaryHintId: hint = %s, id = %d\n", hint.c_str(), i + 1 ); + return i + 1; + } + } + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetAuxiliaryHintId: Invalid hint! [%s]\n", hint.c_str() ); + + return 0; +} + +void Window::SetInputRegion( const Rect< int >& inputRegion ) +{ + ecore_wl2_window_input_region_set( mEventHandler->mEcoreWindow, inputRegion.x, inputRegion.y, inputRegion.width, inputRegion.height ); + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetInputRegion: x = %d, y = %d, w = %d, h = %d\n", inputRegion.x, inputRegion.y, inputRegion.width, inputRegion.height ); +} + +void Window::SetType( Dali::Window::Type type ) +{ + Ecore_Wl2_Window_Type windowType; + + if( type != mType ) + { + switch( type ) + { + case Dali::Window::NORMAL: + { + windowType = ECORE_WL2_WINDOW_TYPE_TOPLEVEL; + break; + } + case Dali::Window::NOTIFICATION: + { + windowType = ECORE_WL2_WINDOW_TYPE_NOTIFICATION; + break; + } + case Dali::Window::UTILITY: + { + windowType = ECORE_WL2_WINDOW_TYPE_UTILITY; + break; + } + case Dali::Window::DIALOG: + { + windowType = ECORE_WL2_WINDOW_TYPE_DIALOG; + break; + } + default: + { + windowType = ECORE_WL2_WINDOW_TYPE_TOPLEVEL; + break; + } + } + + ecore_wl2_window_type_set( mEventHandler->mEcoreWindow, windowType ); + } + + mType = type; +} + +Dali::Window::Type Window::GetType() const +{ + return mType; +} + +bool Window::SetNotificationLevel( Dali::Window::NotificationLevel::Type level ) +{ + if( mType != Dali::Window::NOTIFICATION ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetNotificationLevel: Not supported window type [%d]\n", mType ); + return false; + } + + while( !mEventHandler->mTizenPolicy ) + { + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + } + + int notificationLevel; + + switch( level ) + { + case Dali::Window::NotificationLevel::NONE: + { + notificationLevel = TIZEN_POLICY_LEVEL_NONE; + break; + } + case Dali::Window::NotificationLevel::BASE: + { + notificationLevel = TIZEN_POLICY_LEVEL_DEFAULT; + break; + } + case Dali::Window::NotificationLevel::MEDIUM: + { + notificationLevel = TIZEN_POLICY_LEVEL_MEDIUM; + break; + } + case Dali::Window::NotificationLevel::HIGH: + { + notificationLevel = TIZEN_POLICY_LEVEL_HIGH; + break; + } + case Dali::Window::NotificationLevel::TOP: + { + notificationLevel = TIZEN_POLICY_LEVEL_TOP; + break; + } + default: + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetNotificationLevel: invalid level [%d]\n", level ); + notificationLevel = TIZEN_POLICY_LEVEL_DEFAULT; + break; + } + } + + mEventHandler->mNotificationLevelChangeDone = false; + mEventHandler->mNotificationChangeState = TIZEN_POLICY_ERROR_STATE_NONE; + + tizen_policy_set_notification_level( mEventHandler->mTizenPolicy, ecore_wl2_window_surface_get( mEventHandler->mEcoreWindow ), notificationLevel ); + + int count = 0; + + while( !mEventHandler->mNotificationLevelChangeDone && count < 3 ) + { + ecore_wl2_display_flush(ecore_wl2_connected_display_get(NULL)); + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + count++; + } + + if( !mEventHandler->mNotificationLevelChangeDone ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetNotificationLevel: Level change is failed [%d, %d]\n", level, mEventHandler->mNotificationChangeState ); + return false; + } + else if( mEventHandler->mNotificationChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetNotificationLevel: Permission denied! [%d]\n", level ); + return false; + } + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetNotificationLevel: Level is changed [%d]\n", mEventHandler->mNotificationLevel ); + + return true; +} + +Dali::Window::NotificationLevel::Type Window::GetNotificationLevel() const +{ + if( mType != Dali::Window::NOTIFICATION ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetNotificationLevel: Not supported window type [%d]\n", mType ); + return Dali::Window::NotificationLevel::NONE; + } + + while( !mEventHandler->mTizenPolicy ) + { + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + } + + int count = 0; + + while( !mEventHandler->mNotificationLevelChangeDone && count < 3 ) + { + ecore_wl2_display_flush(ecore_wl2_connected_display_get(NULL)); + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + count++; + } + + if( !mEventHandler->mNotificationLevelChangeDone ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetNotificationLevel: Error! [%d]\n", mEventHandler->mNotificationChangeState ); + return Dali::Window::NotificationLevel::NONE; + } + + Dali::Window::NotificationLevel::Type level; + + switch( mEventHandler->mNotificationLevel ) + { + case TIZEN_POLICY_LEVEL_NONE: + { + level = Dali::Window::NotificationLevel::NONE; + break; + } + case TIZEN_POLICY_LEVEL_DEFAULT: + { + level = Dali::Window::NotificationLevel::BASE; + break; + } + case TIZEN_POLICY_LEVEL_MEDIUM: + { + level = Dali::Window::NotificationLevel::MEDIUM; + break; + } + case TIZEN_POLICY_LEVEL_HIGH: + { + level = Dali::Window::NotificationLevel::HIGH; + break; + } + case TIZEN_POLICY_LEVEL_TOP: + { + level = Dali::Window::NotificationLevel::TOP; + break; + } + default: + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetNotificationLevel: invalid level [%d]\n", mEventHandler->mNotificationLevel ); + level = Dali::Window::NotificationLevel::NONE; + break; + } + } + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetNotificationLevel: level [%d]\n", mEventHandler->mNotificationLevel ); + + return level; +} + +void Window::SetOpaqueState( bool opaque ) +{ + while( !mEventHandler->mTizenPolicy ) + { + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + } + + tizen_policy_set_opaque_state( mEventHandler->mTizenPolicy, ecore_wl2_window_surface_get( mEventHandler->mEcoreWindow ), ( opaque ? 1 : 0 ) ); + + mOpaqueState = opaque; + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetOpaqueState: opaque = %d\n", opaque ); +} + +bool Window::IsOpaqueState() const +{ + return mOpaqueState; +} + +bool Window::SetScreenOffMode(Dali::Window::ScreenOffMode::Type screenOffMode) +{ + while( !mEventHandler->mTizenPolicy ) + { + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + } + + mEventHandler->mScreenOffModeChangeDone = false; + mEventHandler->mScreenOffModeChangeState = TIZEN_POLICY_ERROR_STATE_NONE; + + unsigned int mode = 0; + + switch( screenOffMode ) + { + case Dali::Window::ScreenOffMode::TIMEOUT: + { + mode = 0; + break; + } + case Dali::Window::ScreenOffMode::NEVER: + { + mode = 1; + break; + } + } + + tizen_policy_set_window_screen_mode( mEventHandler->mTizenPolicy, ecore_wl2_window_surface_get( mEventHandler->mEcoreWindow ), mode ); + + int count = 0; + + while( !mEventHandler->mScreenOffModeChangeDone && count < 3 ) + { + ecore_wl2_display_flush(ecore_wl2_connected_display_get(NULL)); + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + count++; + } + + if( !mEventHandler->mScreenOffModeChangeDone ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetScreenOffMode: Screen mode change is failed [%d, %d]\n", screenOffMode, mEventHandler->mScreenOffModeChangeState ); + return false; + } + else if( mEventHandler->mScreenOffModeChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetScreenOffMode: Permission denied! [%d]\n", screenOffMode ); + return false; + } + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetScreenOffMode: Screen mode is changed [%d]\n", mEventHandler->mScreenOffMode ); + + return true; +} + +Dali::Window::ScreenOffMode::Type Window::GetScreenOffMode() const +{ + while( !mEventHandler->mTizenPolicy ) + { + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + } + + int count = 0; + + while( !mEventHandler->mScreenOffModeChangeDone && count < 3 ) + { + ecore_wl2_display_flush(ecore_wl2_connected_display_get(NULL)); + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + count++; + } + + if( !mEventHandler->mScreenOffModeChangeDone ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetScreenOffMode: Error! [%d]\n", mEventHandler->mScreenOffModeChangeState ); + return Dali::Window::ScreenOffMode::TIMEOUT; + } + + Dali::Window::ScreenOffMode::Type screenMode = Dali::Window::ScreenOffMode::TIMEOUT; + + switch( mEventHandler->mScreenOffMode ) + { + case 0: + { + screenMode = Dali::Window::ScreenOffMode::TIMEOUT; + break; + } + case 1: + { + screenMode = Dali::Window::ScreenOffMode::NEVER; + break; + } + } + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetScreenOffMode: screen mode [%d]\n", mEventHandler->mScreenOffMode ); + + return screenMode; +} + +bool Window::SetBrightness( int brightness ) +{ + if( brightness < 0 || brightness > 100 ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetBrightness: Invalid brightness value [%d]\n", brightness ); + return false; + } + + while( !mEventHandler->mTizenDisplayPolicy ) + { + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + } + + mEventHandler->mBrightnessChangeDone = false; + mEventHandler->mBrightnessChangeState = TIZEN_POLICY_ERROR_STATE_NONE; + + tizen_display_policy_set_window_brightness( mEventHandler->mTizenDisplayPolicy, ecore_wl2_window_surface_get( mEventHandler->mEcoreWindow ), brightness ); + + int count = 0; + + while( !mEventHandler->mBrightnessChangeDone && count < 3 ) + { + ecore_wl2_display_flush(ecore_wl2_connected_display_get(NULL)); + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + count++; + } + + if( !mEventHandler->mBrightnessChangeDone ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetBrightness: Brightness change is failed [%d, %d]\n", brightness, mEventHandler->mBrightnessChangeState ); + return false; + } + else if( mEventHandler->mBrightnessChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetBrightness: Permission denied! [%d]\n", brightness ); + return false; + } + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetBrightness: Brightness is changed [%d]\n", mEventHandler->mBrightness ); + + return true; +} + +int Window::GetBrightness() const +{ + while( !mEventHandler->mTizenDisplayPolicy ) + { + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + } + + int count = 0; + + while( !mEventHandler->mBrightnessChangeDone && count < 3 ) + { + ecore_wl2_display_flush(ecore_wl2_connected_display_get(NULL)); + wl_display_dispatch_queue( mEventHandler->mDisplay, mEventHandler->mEventQueue ); + count++; + } + + if( !mEventHandler->mBrightnessChangeDone ) + { + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetBrightness: Error! [%d]\n", mEventHandler->mBrightnessChangeState ); + return 0; + } + + DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::GetBrightness: Brightness [%d]\n", mEventHandler->mBrightness ); + + return mEventHandler->mBrightness; +} + +void Window::SetSize( Dali::Window::WindowSize size ) +{ + if( !mResizeEnabled ) + { + AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" ); + mResizeEnabled = true; + } + + PositionSize positionSize = mSurface->GetPositionSize(); + + if( positionSize.width != size.GetWidth() || positionSize.height != size.GetHeight() ) + { + positionSize.width = size.GetWidth(); + positionSize.height = size.GetHeight(); + + mSurface->MoveResize( positionSize ); + + mAdaptor->SurfaceResizePrepare( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) ); + + // Emit signal + mResizedSignal.Emit( Dali::Window::WindowSize( positionSize.width, positionSize.height ) ); + + mAdaptor->SurfaceResizeComplete( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) ); + } +} + +Dali::Window::WindowSize Window::GetSize() const +{ + PositionSize positionSize = mSurface->GetPositionSize(); + + return Dali::Window::WindowSize( positionSize.width, positionSize.height ); +} + +void Window::SetPosition( Dali::Window::WindowPosition position ) +{ + if( !mResizeEnabled ) + { + AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" ); + mResizeEnabled = true; + } + + PositionSize positionSize = mSurface->GetPositionSize(); + + if( positionSize.x != position.GetX() || positionSize.y != position.GetY() ) + { + positionSize.x = position.GetX(); + positionSize.y = position.GetY(); + + mSurface->MoveResize( positionSize ); + } +} + +Dali::Window::WindowPosition Window::GetPosition() const +{ + PositionSize positionSize = mSurface->GetPositionSize(); + + return Dali::Window::WindowPosition( positionSize.x, positionSize.y ); +} + +void Window::SetTransparency( bool transparent ) +{ + ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) ); + if( wlSurface ) + { + wlSurface->SetTransparency( transparent ); + } +} + +} // Adaptor + +} // Internal + +} // Dali + +#pragma GCC diagnostic pop diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-render-surface-ecore-wl2.cpp b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-render-surface-ecore-wl2.cpp new file mode 100644 index 0000000..0f57675 --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-render-surface-ecore-wl2.cpp @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2017 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 + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +#if defined(DEBUG_ENABLED) +extern Debug::Filter* gRenderSurfaceLogFilter; +#endif + +namespace ECore +{ + +namespace +{ + +const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved + +} // unnamed namespace + +WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, + Any surface, + const std::string& name, + bool isTransparent) +: EcoreWlRenderSurface( positionSize, surface, name, isTransparent ), + mWlWindow( NULL ), + mEcore_Wl2_display( NULL ), + mWlSurface( NULL ), + mEglWindow( NULL ), + mThreadSynchronization( NULL ), + mRotationTrigger( NULL ), + mRotationAngle( 0 ), + mScreenRotationAngle( 0 ), + mRotationSupported( false ), + mRotationFinished( true ), + mScreenRotationFinished( true ), + mResizeFinished( true ) +{ + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" ); + Init( surface ); +} + +WindowRenderSurface::~WindowRenderSurface() +{ + if( mEglWindow != NULL ) + { + wl_egl_window_destroy(mEglWindow); + mEglWindow = NULL; + } + + if( mOwnSurface ) + { + ecore_wl2_window_free( mWlWindow ); + } + + if( mRotationTrigger ) + { + delete mRotationTrigger; + } + +} + +Ecore_Wl2_Window* WindowRenderSurface::GetDrawable() +{ + // already an e-core type + return mWlWindow; +} + +Any WindowRenderSurface::GetSurface() +{ + // already an e-core type + return Any( mWlWindow ); +} + +Ecore_Wl2_Window* WindowRenderSurface::GetWlWindow() +{ + return mWlWindow; +} + +void WindowRenderSurface::RequestRotation( int angle, int width, int height ) +{ + if( !mRotationSupported ) + { + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" ); + return; + } + + if( !mRotationTrigger ) + { + TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface(); + mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ); + } + + mPositionSize.width = width; + mPositionSize.height = height; + + mRotationAngle = angle; + mRotationFinished = false; + + ecore_wl2_window_rotation_set( mWlWindow, mRotationAngle ); + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle ); +} + +void WindowRenderSurface::OutputTransformed() +{ + int transform; + + if( ecore_wl2_window_ignore_output_transform_get( mWlWindow ) ) + { + transform = 0; + } + else + { + transform = ecore_wl2_output_transform_get( ecore_wl2_window_output_find( mWlWindow ) ); + } + + mScreenRotationAngle = transform * 90; + mScreenRotationFinished = false; + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle ); +} + +void WindowRenderSurface::SetTransparency( bool transparent ) +{ + ecore_wl2_window_alpha_set( mWlWindow, transparent ); +} + +void WindowRenderSurface::InitializeEgl( EglInterface& eglIf ) +{ + DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); + + Internal::Adaptor::EglImplementation& eglImpl = static_cast( eglIf ); + + eglImpl.ChooseConfig(true, mColorDepth); +} + +void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf ) +{ + DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); + + Internal::Adaptor::EglImplementation& eglImpl = static_cast( eglIf ); + + // create the EGL window + if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 ) + { + mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height ); + } + else + { + mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width ); + } + + EGLNativeWindowType windowType( mEglWindow ); + eglImpl.CreateSurfaceWindow( windowType, mColorDepth ); + + // Check capability + wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) ); + if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) + { + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability ); + mRotationSupported = true; + } + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle ); +} + +void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf ) +{ + DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); + + Internal::Adaptor::EglImplementation& eglImpl = static_cast( eglIf ); + eglImpl.DestroySurface(); + + if( mEglWindow != NULL ) + { + wl_egl_window_destroy(mEglWindow); + mEglWindow = NULL; + } +} + +bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl ) +{ + DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); + + if( mEglWindow != NULL ) + { + wl_egl_window_destroy(mEglWindow); + mEglWindow = NULL; + } + + if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 ) + { + mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height ); + } + else + { + mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width ); + } + + // Set screen rotation + mScreenRotationFinished = false; + + Internal::Adaptor::EglImplementation& eglImpl = static_cast( egl ); + EGLNativeWindowType windowType( mEglWindow ); + return eglImpl.ReplaceSurfaceWindow( windowType ); +} + +void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize ) +{ + bool needToMove = false; + bool needToResize = false; + + // check moving + if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) || + (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) ) + { + needToMove = true; + } + + // check resizing + if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) || + (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) ) + { + needToResize = true; + } + + if( needToMove || needToResize ) + { + ecore_wl2_window_geometry_set( mWlWindow, positionSize.x, positionSize.y, positionSize.width, positionSize.height ); + if (needToResize) + { + mResizeFinished = false; + } + } + + mPositionSize = positionSize; + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height ); +} + +void WindowRenderSurface::Map() +{ + ecore_wl2_window_show(mWlWindow); +} + +void WindowRenderSurface::StartRender() +{ +} + +bool WindowRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface ) +{ + if( resizingSurface ) + { +#ifdef OVER_TIZEN_VERSION_4 + // Window rotate or screen rotate + if( !mRotationFinished || !mScreenRotationFinished ) + { + wl_egl_window_rotation rotation; + wl_output_transform bufferTransform; + int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360; + + switch( totalAngle ) + { + case 0: + { + rotation = ROTATION_0; + bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL; + break; + } + case 90: + { + rotation = ROTATION_270; + bufferTransform = WL_OUTPUT_TRANSFORM_90; + break; + } + case 180: + { + rotation = ROTATION_180; + bufferTransform = WL_OUTPUT_TRANSFORM_180; + break; + } + case 270: + { + rotation = ROTATION_90; + bufferTransform = WL_OUTPUT_TRANSFORM_270; + break; + } + default: + { + rotation = ROTATION_0; + bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL; + break; + } + } + + wl_egl_window_set_rotation( mEglWindow, rotation ); + + wl_egl_window_set_buffer_transform( mEglWindow, bufferTransform ); + + // Reset only screen rotation flag + mScreenRotationFinished = true; + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle ); + } + + // Only window rotate + if( !mRotationFinished ) + { + wl_output_transform windowTransform; + + switch( mRotationAngle ) + { + case 0: + { + windowTransform = WL_OUTPUT_TRANSFORM_NORMAL; + break; + } + case 90: + { + windowTransform = WL_OUTPUT_TRANSFORM_90; + break; + } + case 180: + { + windowTransform = WL_OUTPUT_TRANSFORM_180; + break; + } + case 270: + { + windowTransform = WL_OUTPUT_TRANSFORM_270; + break; + } + default: + { + windowTransform = WL_OUTPUT_TRANSFORM_NORMAL; + break; + } + } + + wl_egl_window_set_window_transform( mEglWindow, windowTransform ); + } +#endif + + // Resize case + if( !mResizeFinished ) + { + wl_egl_window_resize( mEglWindow, mPositionSize.width, mPositionSize.height, mPositionSize.x, mPositionSize.y ); + mResizeFinished = true; + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" ); + } + } + + return true; +} + +void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface ) +{ + if( resizingSurface ) + { + if( !mRotationFinished ) + { + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" ); + + mRotationTrigger->Trigger(); + + if( mThreadSynchronization ) + { + // Wait until the event-thread complete the rotation event processing + mThreadSynchronization->PostRenderWaitForCompletion(); + } + } + } + + Internal::Adaptor::EglImplementation& eglImpl = static_cast( egl ); + eglImpl.SwapBuffers(); + + if( mRenderNotification ) + { + mRenderNotification->Trigger(); + } +} + +void WindowRenderSurface::StopRender() +{ +} + +void WindowRenderSurface::SetViewMode( ViewMode viewMode ) +{ + //FIXME +} + +void WindowRenderSurface::CreateWlRenderable() +{ + // TODO :: + // use default display name as getenv("WAYLAND_DISPLAY") + // If specific name is needed, + // the name will be changed and should change the code of using ecore_wl2_connected_display_get() + // Because default name is used in ecore_wl2_connected_display_get()'s use case. + if ( mEcore_Wl2_display == NULL ) + { + mEcore_Wl2_display = ecore_wl2_display_connect(NULL); + } + if ( mEcore_Wl2_display == NULL ) + { + DALI_LOG_ERROR("Fail to connect ecore_wl2_display"); + return; + } + + // if width or height are zero, go full screen. + if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) ) + { + // Default window size == screen size + mPositionSize.x = 0; + mPositionSize.y = 0; + + ecore_wl2_display_screen_size_get( mEcore_Wl2_display, &mPositionSize.width, &mPositionSize.height ); + } + + mWlWindow = ecore_wl2_window_new( mEcore_Wl2_display, NULL, mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height ); + if ( mWlWindow == 0 ) + { + DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window"); + } + + mWlSurface = ecore_wl2_window_surface_get( mWlWindow ); + + if( mColorDepth == COLOR_DEPTH_32 ) + { + ecore_wl2_window_alpha_set( mWlWindow, true ); + } + else + { + ecore_wl2_window_alpha_set( mWlWindow, false ); + } + + ecore_wl2_window_type_set( mWlWindow, ECORE_WL2_WINDOW_TYPE_TOPLEVEL); + + // Get output transform + if( !ecore_wl2_window_ignore_output_transform_get( mWlWindow ) ) + { + Ecore_Wl2_Output* output = ecore_wl2_window_output_find( mWlWindow ); + + int transform = ecore_wl2_output_transform_get( output ); + + mScreenRotationAngle = transform * 90; + mScreenRotationFinished = false; + } +} + +void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId ) +{ + mWlWindow = AnyCast< Ecore_Wl2_Window* >( surfaceId ); +} + +void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization ) +{ + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" ); + + mThreadSynchronization = &threadSynchronization; +} + +void WindowRenderSurface::ReleaseLock() +{ + // Nothing to do. +} + +void WindowRenderSurface::ProcessRotationRequest() +{ + mRotationFinished = true; + + ecore_wl2_window_rotation_change_done_send( mWlWindow, mRotationAngle, mPositionSize.width, mPositionSize.height ); + + DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" ); + + if( mThreadSynchronization ) + { + mThreadSynchronization->PostRenderComplete(); + } +} + +} // namespace ECore + +} // namespace Dali diff --git a/dali/internal/window-system/tizen-wayland/ecore-wl2/window-render-surface-ecore-wl2.h b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-render-surface-ecore-wl2.h new file mode 100644 index 0000000..22a3233 --- /dev/null +++ b/dali/internal/window-system/tizen-wayland/ecore-wl2/window-render-surface-ecore-wl2.h @@ -0,0 +1,203 @@ +#ifndef __DALI_INTERNAL_ECORE_WL2_WINDOW_RENDER_SURFACE_H__ +#define __DALI_INTERNAL_ECORE_WL2_WINDOW_RENDER_SURFACE_H__ + +/* + * Copyright (c) 2017 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 + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace ECore +{ + +/** + * @copydoc Dali::ECore::EcoreWlRenderSurface. + * Window specialization. + */ +class WindowRenderSurface : public EcoreWlRenderSurface +{ +public: + + /** + * Uses an Wayland surface to render to. + * @param [in] positionSize the position and size of the surface + * @param [in] surface can be a Wayland-window or Wayland-pixmap (type must be unsigned int). + * @param [in] name optional name of surface passed in + * @param [in] isTransparent if it is true, surface has 32 bit color depth, otherwise, 24 bit + */ + WindowRenderSurface( Dali::PositionSize positionSize, + Any surface, + const std::string& name, + bool isTransparent = false ); + + /** + * @copydoc Dali::ECore::EcoreWlRenderSurface::~EcoreWlRenderSurface + */ + virtual ~WindowRenderSurface(); + +public: // API + + /** + * @copydoc Dali::RenderSurface::GetDrawable() + */ + virtual Ecore_Wl2_Window* GetDrawable(); + + /** + * Map window + */ + virtual void Map(); + + /** + * @copydoc Dali::ECore::EcoreWlRenderSurface::GetSurface() + */ + virtual Any GetSurface(); + + /** + * @copydoc Dali::ECore::EcoreWlRenderSurface::GetWlWindow() + */ + virtual Ecore_Wl2_Window* GetWlWindow(); + + /** + * Request surface rotation + * @param[in] angle A new angle of the surface + * @param[in] width A new width of the surface + * @param[in] height A new height of the surface + */ + void RequestRotation( int angle, int width, int height ); + + /** + * Notify output is transformed. + */ + void OutputTransformed(); + + /** + * @brief Sets whether the surface is transparent or not. + * + * @param[in] transparent Whether the surface is transparent + */ + void SetTransparency( bool transparent ); + +public: // from Dali::RenderSurface + + /** + * @copydoc Dali::RenderSurface::InitializeEgl() + */ + virtual void InitializeEgl( EglInterface& egl ); + + /** + * @copydoc Dali::RenderSurface::CreateEglSurface() + */ + virtual void CreateEglSurface( EglInterface& egl ); + + /** + * @copydoc Dali::RenderSurface::DestroyEglSurface() + */ + virtual void DestroyEglSurface( EglInterface& egl ); + + /** + * @copydoc Dali::RenderSurface::ReplaceEGLSurface() + */ + virtual bool ReplaceEGLSurface( EglInterface& egl ); + + /** + * @copydoc Dali::RenderSurface::MoveResize() + */ + virtual void MoveResize( Dali::PositionSize positionSize); + + /** + * @copydoc Dali::RenderSurface::SetViewMode() + */ + void SetViewMode( ViewMode viewMode ); + + /** + * @copydoc Dali::RenderSurface::StartRender() + */ + virtual void StartRender(); + + /** + * @copydoc Dali::RenderSurface::PreRender() + */ + virtual bool PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface ); + + /** + * @copydoc Dali::RenderSurface::PostRender() + */ + virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface ); + + /** + * @copydoc Dali::RenderSurface::StopRender() + */ + virtual void StopRender(); + + /** + * @copydoc Dali::RenderSurface::SetThreadSynchronization + */ + virtual void SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization ); + + /** + * @copydoc Dali::RenderSurface::ReleaseLock() + */ + virtual void ReleaseLock(); + +protected: + + /** + * Create WlWindow + */ + virtual void CreateWlRenderable(); + + /** + * @copydoc Dali::Internal::Adaptor::ECore::EcoreWlRenderSurface::UseExistingRenderable + */ + virtual void UseExistingRenderable( unsigned int surfaceId ); + +private: + + /** + * Used as the callback for the rotation-trigger. + */ + void ProcessRotationRequest(); + +private: // Data + + Ecore_Wl2_Window* mWlWindow; ///< Wayland-Window + Ecore_Wl2_Display* mEcore_Wl2_display; + wl_surface* mWlSurface; + wl_egl_window* mEglWindow; + ThreadSynchronizationInterface* mThreadSynchronization; + TriggerEventInterface* mRotationTrigger; + int mRotationAngle; + int mScreenRotationAngle; + bool mRotationSupported; + bool mRotationFinished; + bool mScreenRotationFinished; + bool mResizeFinished; + +}; // class WindowRenderSurface + +} // namespace ECore + +} // namespace Dali + +#endif // __DALI_INTERNAL_ECORE_WL2_WINDOW_RENDER_SURFACE_H__ diff --git a/dali/internal/window-system/tizen/native-render-surface-tizen.cpp b/dali/internal/window-system/tizen/native-render-surface-tizen.cpp index de42ab0..d32c610 100644 --- a/dali/internal/window-system/tizen/native-render-surface-tizen.cpp +++ b/dali/internal/window-system/tizen/native-render-surface-tizen.cpp @@ -23,7 +23,11 @@ #include #include +#ifdef ECORE_WL2 +#include +#else #include +#endif #include #include #include @@ -76,7 +80,11 @@ NativeRenderSurface::NativeRenderSurface(Dali::PositionSize positionSize, bool isTransparent) : mImpl( new Impl( positionSize, name, isTransparent ) ) { +#ifdef ECORE_WL2 + ecore_wl2_init(); +#else ecore_wl_init(NULL); +#endif CreateNativeRenderable(); setenv( "EGL_PLATFORM", "tbm", 1 ); } diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index fd534cc..604de53 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -15,7 +15,8 @@ %global __provides_exclude_from ^.*\\.(wearable|mobile|tv|ivi|common)$ %endif -%bcond_with wayland +%bcond_without wayland +%bcond_with x Name: dali-adaptor Summary: The DALi Tizen Adaptor @@ -96,7 +97,11 @@ BuildRequires: wayland-devel BuildRequires: wayland-extension-client-devel # dali-adaptor uses ecore mainloop +%if 0%{?tizen_version_major} >= 5 +BuildRequires: pkgconfig(ecore-wl2) +%else BuildRequires: pkgconfig(ecore-wayland) +%endif # dali-adaptor needs tbm_surface in tizen 3.0 wayland BuildRequires: pkgconfig(libtbm) @@ -450,12 +455,16 @@ CXXFLAGS+=" -D_ARCH_ARM_ -lgcc" %if %{with wayland} CFLAGS+=" -DWAYLAND" CXXFLAGS+=" -DWAYLAND" +%if 0%{?tizen_version_major} >= 5 +CFLAGS+=" -DECORE_WL2 -DEFL_BETA_API_SUPPORT" +CXXFLAGS+=" -DECORE_WL2 -DEFL_BETA_API_SUPPORT" +%endif configure_flags="--enable-wayland" %endif # Use this conditional when Tizen version is 4.x or greater -%if 0%{?tizen_version_major} >= 4 -CXXFLAGS+=" -DOVER_TIZEN_VERSION_4" +%if 0%{?tizen_version_major} >= 5 +CXXFLAGS+=" -DOVER_TIZEN_VERSION_5" %endif %if 0%{?tizen_2_2_compatibility}