[dali_2.0.8] Merge branch 'devel/master' 52/251152/1
authorRichard Huang <r.huang@samsung.com>
Fri, 8 Jan 2021 14:36:22 +0000 (14:36 +0000)
committerRichard Huang <r.huang@samsung.com>
Fri, 8 Jan 2021 14:36:22 +0000 (14:36 +0000)
Change-Id: I779907c7bd293b302d03c539baf5aee65a263255

64 files changed:
.gitignore
README.md
build/tizen/.gitignore
build/tizen/CMakeLists.txt
build/tizen/deps-check.cmake
build/tizen/profiles/macos-profile.cmake [new file with mode: 0644]
dali/devel-api/adaptor-framework/web-engine-plugin.h
dali/devel-api/adaptor-framework/web-engine.cpp [changed mode: 0644->0755]
dali/devel-api/adaptor-framework/web-engine.h
dali/internal/accessibility/file.list
dali/internal/adaptor/common/combined-update-render-controller.cpp
dali/internal/adaptor/common/combined-update-render-controller.h
dali/internal/adaptor/file.list
dali/internal/adaptor/macos/framework-mac.mm [new file with mode: 0644]
dali/internal/clipboard/file.list
dali/internal/graphics/file.list
dali/internal/graphics/macos/egl-image-extensions.cpp [new file with mode: 0644]
dali/internal/imaging/file.list
dali/internal/imaging/macos/native-image-source-factory-mac.cpp [new file with mode: 0644]
dali/internal/imaging/macos/native-image-source-factory-mac.h [new file with mode: 0644]
dali/internal/imaging/macos/native-image-source-impl-mac.cpp [new file with mode: 0644]
dali/internal/imaging/macos/native-image-source-impl-mac.h [new file with mode: 0644]
dali/internal/input/file.list
dali/internal/input/macos/input-method-context-factory-mac.cpp [new file with mode: 0644]
dali/internal/input/macos/input-method-context-impl-mac.cpp [new file with mode: 0644]
dali/internal/input/macos/input-method-context-impl-mac.h [new file with mode: 0644]
dali/internal/input/macos/key-mapping-mac.cpp [new file with mode: 0644]
dali/internal/input/macos/virtual-keyboard-impl-mac.cpp [new file with mode: 0644]
dali/internal/system/common/abort-handler.h
dali/internal/system/file.list
dali/internal/system/macos/callback-manager-mac.h [new file with mode: 0644]
dali/internal/system/macos/callback-manager-mac.mm [new file with mode: 0644]
dali/internal/system/macos/file-descriptor-monitor-macos.cpp [new file with mode: 0644]
dali/internal/system/macos/timer-impl-mac.cpp [new file with mode: 0644]
dali/internal/system/macos/trigger-event.h [new file with mode: 0644]
dali/internal/system/macos/trigger-event.mm [new file with mode: 0644]
dali/internal/system/macos/widget-application-impl-mac.cpp [new file with mode: 0644]
dali/internal/system/macos/widget-application-impl-mac.h [new file with mode: 0644]
dali/internal/text/text-abstraction/font-client-impl.cpp
dali/internal/text/text-abstraction/font-client-plugin-impl.cpp
dali/internal/web-engine/common/web-engine-impl.cpp
dali/internal/web-engine/common/web-engine-impl.h [changed mode: 0644->0755]
dali/internal/window-system/file.list
dali/internal/window-system/macos/display-connection-factory-mac.cpp [new file with mode: 0644]
dali/internal/window-system/macos/display-connection-factory-mac.h [new file with mode: 0644]
dali/internal/window-system/macos/display-connection-impl-mac.cpp [new file with mode: 0644]
dali/internal/window-system/macos/display-connection-impl-mac.h [new file with mode: 0644]
dali/internal/window-system/macos/render-surface-factory-mac.cpp [new file with mode: 0644]
dali/internal/window-system/macos/render-surface-factory-mac.h [new file with mode: 0644]
dali/internal/window-system/macos/window-base-mac.h [new file with mode: 0644]
dali/internal/window-system/macos/window-base-mac.mm [new file with mode: 0644]
dali/internal/window-system/macos/window-factory-mac.cpp [new file with mode: 0644]
dali/internal/window-system/macos/window-factory-mac.h [new file with mode: 0644]
dali/internal/window-system/macos/window-render-surface-cocoa.cpp [new file with mode: 0644]
dali/internal/window-system/macos/window-render-surface-cocoa.h [new file with mode: 0644]
dali/internal/window-system/macos/window-system-mac.mm [new file with mode: 0644]
dali/internal/window-system/windows/platform-implement-win.cpp
dali/public-api/dali-adaptor-version.cpp
packaging/dali-adaptor.spec
third-party/file.list
third-party/macos-platform/environment.cpp [new file with mode: 0644]
third-party/macos-platform/extern-definitions.h [new file with mode: 0644]
third-party/macos-platform/sys/prctl.h [new file with mode: 0644]
third-party/macos-platform/thread.cpp [new file with mode: 0644]

index 3480ca9..0fcd0ac 100644 (file)
@@ -39,3 +39,5 @@ tags
 /debuglinks.list
 /debugsources.list
 /dali/internal/adaptor/common/system-cache-path.cpp
+.clangd
+compile_commands.json
index e3bed27..42afb8d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@
       * [3. Building for MS Windows](#3-building-for-ms-windows)
          * Build with the Visual Studio project.
          * Build with CMake.
+      * [4. Building for MacOS](#4-building-for-macos)
 
 # Build Instructions
 
@@ -101,3 +102,22 @@ vcpkg-script folder in the windows-dependencies repository.
     - INSTALL_CMAKE_MODULES ---> Whether to install the CMake modules (Used by the CMake command find_package() to find previously installed libraries).
     - PROFILE_LCASE         ---> The platform (must be windows).
     - ENABLE_DEBUG          ---> Whether to build with debug enabled.
+
+## 4. Building for MacOS
+
+It is assumed that the DALi environment has been set up & that DALi Core has been built accordingly.
+
+To build the repository enter the 'build/tizen' folder:
+```zsh
+% cd dali-adaptor/build/tizen
+```
+Then run the following command to set up the build:
+```zsh
+% cmake -DCMAKE_INSTALL_PREFIX=$DESKTOP_PREFIX -DCMAKE_TOOLCHAIN_FILE=$VCPKG_FOLDER/scripts/buildsystems/vcpkg.cmake -DINSTALL_CMAKE_MODULES=ON -DENABLE_PROFILE=MACOS -DPROFILE_LCASE=macos
+```
+If a Debug build is required, then add `-DCMAKE_BUILD_TYPE=Debug -DENABLE_DEBUG=ON`
+
+To build, run:
+```zsh
+% make install -j8
+```
index 8469aaf..1ab58fe 100644 (file)
@@ -12,3 +12,5 @@ doc
 install_manifest.txt
 libdali2-adaptor.so.*
 linker-test
+*config.cmake
+*.dylib
index 18b4591..441916f 100644 (file)
@@ -164,10 +164,16 @@ IF( WIN32 )
   SET( THIRD_PARTY_WINDOWS_PLATFORM ${ROOT_SRC_DIR}/third-party/windows-platform )
 ENDIF()
 
+SET( THIRD_PARTY_MACOS_PLATFORM "" )
+IF( APPLE )
+  SET( THIRD_PARTY_MACOS_PLATFORM ${ROOT_SRC_DIR}/third-party/macos-platform )
+ENDIF()
+
 INCLUDE_DIRECTORIES(
   ${ROOT_SRC_DIR}
   ${PROFILE_INCLUDE_DIRECTORIES}
   ${THIRD_PARTY_WINDOWS_PLATFORM}
+  ${THIRD_PARTY_MACOS_PLATFORM}
   ${VCPKG_INCLUDE_DIR}
   ${INCLUDE_DIR}
 )
@@ -230,7 +236,7 @@ IF( INSTALL_CMAKE_MODULES )
   install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake DESTINATION share/${name})
 
   # Install the pdb file.
-  IF( ENABLE_DEBUG )
+  IF( ENABLE_DEBUG AND WIN32 )
     install( FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/${name}.pdb DESTINATION ${BIN_DIR} )
   ENDIF()
 ELSE()
@@ -290,7 +296,7 @@ SET( package_doxy_dir ${ADAPTOR_ROOT}/doc )
 INCLUDE( ${ADAPTOR_ROOT}/doc/file.list )
 INSTALL( FILES ${package_doxy_files} DESTINATION ${packagedoxydir} )
 
-IF( NOT UBUNTU_PROFILE AND NOT ANDROID_PROFILE AND NOT WINDOWS_PROFILE )
+IF( NOT UBUNTU_PROFILE AND NOT ANDROID_PROFILE AND NOT WINDOWS_PROFILE AND NOT MACOS_PROFILE )
   INSTALL( FILES ${public_api_adaptor_tizen_header_files} DESTINATION ${tizenadaptorframeworkpublicapidir} )
   IF( NOT WAYLAND )
     INSTALL( FILES ${devel_api_adaptor_tizen_x11_header_files} DESTINATION ${tizenadaptorframeworkdevelapidir} )
index 6ed3a2d..702b433 100644 (file)
@@ -42,7 +42,7 @@ IF( NOT enable_profile )
 ENDIF()
 
 # Test for profile and exit if something wrong
-SET( VALID_PROFILES COMMON MOBILE WEARABLE TV IVI UBUNTU ANDROID WINDOWS )
+SET( VALID_PROFILES COMMON MOBILE WEARABLE TV IVI UBUNTU ANDROID WINDOWS MACOS )
 LIST( FIND VALID_PROFILES ${enable_profile} RESULT )
 IF( RESULT EQUAL -1 )
   MESSAGE( FATAL_ERROR "Invalid profile!" )
@@ -216,7 +216,7 @@ IF( DEFINED ENV{FONT_CONFIGURATION_FILE} )
   SET( fontConfigurationFile $ENV{FONT_CONFIGURATION_FILE} )
 ENDIF()
 
-IF( UBUNTU_PROFILE )
+IF( UBUNTU_PROFILE OR MACOS_PROFILE )
   SET( cachePath $ENV{HOME} )
 ELSE()
   SET( cachePath /home/owner )
@@ -265,31 +265,33 @@ SET( DALI_CFLAGS
   -Wall
 )
 
-# Default set of linked librarires
-SET( DALI_LDFLAGS
-  ${DALICORE_LDFLAGS}
-  ${OPENGLES20_LDFLAGS}
-  ${FREETYPE_LDFLAGS}
-  ${FONTCONFIG_LDFLAGS}
-  ${CAIRO_LDFLAGS}
-  ${PNG_LDFLAGS}
-  ${WEBP_LDFLAGS}
-  ${WEBP_DEMUX_LDFLAGS}
-  ${DLOG_LDFLAGS}
-  ${VCONF_LDFLAGS}
-  ${EXIF_LDFLAGS}
-  ${TTS_LDFLAGS}
-  ${CAPI_SYSTEM_SENSOR_LDFLAGS}
-  ${LIBDRM_LDFLAGS}
-  ${LIBEXIF_LDFLAGS}
-  ${LIBCURL_LDFLAGS}
-  ${LIBCRYPTO_LDFLAGS}
-  ${HARFBUZZ_LDFLAGS}
-  ${UTILX_LDFLAGS}
-  -lgif
-  -lturbojpeg
-  -ljpeg
-)
+IF (NOT APPLE)
+  # Default set of linked librarires
+  SET( DALI_LDFLAGS
+    ${DALICORE_LDFLAGS}
+    ${OPENGLES20_LDFLAGS}
+    ${FREETYPE_LDFLAGS}
+    ${FONTCONFIG_LDFLAGS}
+    ${CAIRO_LDFLAGS}
+    ${PNG_LDFLAGS}
+    ${WEBP_LDFLAGS}
+    ${WEBP_DEMUX_LDFLAGS}
+    ${DLOG_LDFLAGS}
+    ${VCONF_LDFLAGS}
+    ${EXIF_LDFLAGS}
+    ${TTS_LDFLAGS}
+    ${CAPI_SYSTEM_SENSOR_LDFLAGS}
+    ${LIBDRM_LDFLAGS}
+    ${LIBEXIF_LDFLAGS}
+    ${LIBCURL_LDFLAGS}
+    ${LIBCRYPTO_LDFLAGS}
+    ${HARFBUZZ_LDFLAGS}
+    ${UTILX_LDFLAGS}
+    -lgif
+    -lturbojpeg
+    -ljpeg
+  )
+ENDIF()
 
 # Android includes pthread with android lib
 if( NOT ANDROID_PROFILE )
diff --git a/build/tizen/profiles/macos-profile.cmake b/build/tizen/profiles/macos-profile.cmake
new file mode 100644 (file)
index 0000000..6430fca
--- /dev/null
@@ -0,0 +1,123 @@
+# PROFILE: MACOS
+
+# Set the sources
+SET( SOURCES
+        ${adaptor_accessibility_common_src_files}
+        ${adaptor_accessibility_macos_src_files}
+        ${adaptor_adaptor_common_src_files}
+        ${adaptor_adaptor_macos_src_files}
+        ${adaptor_clipboard_common_src_files}
+        ${adaptor_clipboard_macos_src_files}
+        ${adaptor_framework_generic_src_files}
+        ${devel_api_src_files}
+        ${adaptor_devel_api_text_abstraction_src_files}
+        ${adaptor_graphics_common_src_files}
+        ${adaptor_graphics_gles_src_files}
+        ${adaptor_graphics_macos_src_files}
+        ${adaptor_haptics_common_src_files}
+        ${adaptor_imaging_common_src_files}
+        ${adaptor_imaging_macos_src_files}
+        ${adaptor_input_common_src_files}
+        ${adaptor_input_macos_src_files}
+        ${adaptor_integration_api_src_files}
+        ${adaptor_legacy_common_src_files}
+        ${adaptor_network_common_src_files}
+        ${adaptor_offscreen_common_src_files}
+        ${adaptor_public_api_src_files}
+        ${adaptor_sensor_common_src_files}
+        ${adaptor_sensor_macos_src_files}
+        ${adaptor_styling_common_src_files}
+        ${adaptor_system_common_src_files}
+        ${adaptor_system_macos_src_files}
+        ${adaptor_system_macos_src_files}
+        ${adaptor_text_common_src_files}
+        ${adaptor_text_macos_src_files}
+        ${adaptor_resampler_src_files}
+        ${adaptor_vector_animation_common_src_files}
+        ${adaptor_vector_image_common_src_files}
+        ${adaptor_video_common_src_files}
+        ${adaptor_web_engine_common_src_files}
+        ${adaptor_window_system_common_src_files}
+        ${adaptor_macos_platform_src_files}
+        ${adaptor_trace_common_src_files}
+        ${adaptor_thread_common_src_files}
+        ${adaptor_window_system_macos_src_files}
+        ${devel_api_text_abstraction_src_files}
+        ${adaptor_addons_common_src_files}
+        ${adaptor_addons_macos_src_files}
+        ${static_libraries_glyphy_src_files}
+        ${static_libraries_libunibreak_src_files}
+        ${static_libraries_nanosvg_src_files}
+)
+
+IF( ENABLE_NETWORK_LOGGING )
+    SET( SOURCES ${SOURCES}
+          ${adaptor_performance_logging_src_files}
+    )
+ENDIF()
+
+IF( ENABLE_TRACE )
+    SET( SOURCES ${SOURCES}
+        ${adaptor_trace_generic_src_files}
+      )
+ENDIF()
+
+FIND_PACKAGE( curl REQUIRED )
+FIND_LIBRARY( EXIF_LIBRARY NAMES libexif REQUIRED )
+
+FIND_PACKAGE( png REQUIRED )
+FIND_PACKAGE( gif REQUIRED )
+FIND_PACKAGE( jpeg REQUIRED )
+FIND_LIBRARY( TURBO_JPEG_LIBRARY NAMES turbojpeg REQUIRED )
+
+FIND_PACKAGE( freetype REQUIRED )
+FIND_PACKAGE( harfbuzz REQUIRED )
+FIND_LIBRARY( FRIBIDI_LIBRARY NAMES fribidi REQUIRED )
+
+FIND_PACKAGE( unofficial-angle REQUIRED )
+FIND_PACKAGE( unofficial-cairo REQUIRED )
+FIND_PACKAGE( dali2-core REQUIRED)
+
+FIND_PACKAGE( WebP REQUIRED )
+SET(DALI_WEBP_AVAILABLE 1)
+ADD_DEFINITIONS( -DDALI_WEBP_AVAILABLE )
+
+FIND_LIBRARY(OpenGL OpenGL)
+FIND_LIBRARY(IOSurface IOSurface)
+FIND_LIBRARY(QuartzCore QuartzCore)
+FIND_LIBRARY(Foundation Foundation)
+FIND_LIBRARY(Cocoa Cocoa)
+
+# Set the linker flags
+SET(REQUIRED_LIBS
+  CURL::libcurl
+  ${GETOPT_LIBRARY}
+  ${EXIF_LIBRARY}
+  ${PNG_LIBRARIES}
+  ${GIF_LIBRARIES}
+  ${FONTCONFIG_LDFLAGS}
+  ${CAIRO_LDFLAGS}
+  JPEG::JPEG
+  ${TURBO_JPEG_LIBRARY}
+  Freetype::Freetype
+  harfbuzz::harfbuzz
+  ${FRIBIDI_LIBRARY}
+  unofficial::angle::libEGL
+  unofficial::angle::libGLESv2
+  unofficial::cairo::cairo
+  WebP::webp
+  WebP::webpdemux
+  dali2-core::dali2-core
+  ${OpenGL}
+  ${IOSurface}
+  ${Foundation}
+  ${QuartzCore}
+  ${Cocoa}
+  -pthread
+)
+
+# Set compile options
+ADD_COMPILE_OPTIONS(
+  ${FONTCONFIG_CFLAGS}
+  ${CAIRO_CFLAGS}
+)
index 7b42614..5914637 100644 (file)
@@ -331,6 +331,11 @@ public:
   virtual bool SendKeyEvent(const KeyEvent& event) = 0;
 
   /**
+   * @brief Sets focus.
+   */
+  virtual void SetFocus( bool focused ) = 0;
+
+  /**
    * @brief Connects to this signal to be notified when page loading is started.
    *
    * @return A signal object to connect with.
old mode 100644 (file)
new mode 100755 (executable)
index f1a7420..69c2b79
@@ -242,6 +242,11 @@ bool WebEngine::SendKeyEvent(const KeyEvent& event)
   return GetImplementation(*this).SendKeyEvent(event);
 }
 
+void WebEngine::SetFocus( bool focused )
+{
+  GetImplementation( *this ).SetFocus( focused );
+}
+
 Dali::WebEnginePlugin::WebEnginePageLoadSignalType& WebEngine::PageLoadStartedSignal()
 {
   return GetImplementation(*this).PageLoadStartedSignal();
index dc72683..f3622ab 100644 (file)
@@ -314,6 +314,11 @@ public:
   bool SendKeyEvent(const KeyEvent& event);
 
   /**
+   * @brief Set focus.
+   */
+  void SetFocus( bool focused );
+
+  /**
    * @brief Connects to this signal to be notified when page loading is started.
    *
    * @return A signal object to connect with.
index 30f853a..bfdad24 100755 (executable)
@@ -66,3 +66,9 @@ SET( adaptor_accessibility_atspi_bridge_src_files
 SET( adaptor_accessibility_atspi_dummy_src_files
     ${adaptor_accessibility_dir}/bridge/dummy-atspi.cpp
 )
+
+# module: accessibility, backend: macos
+SET( adaptor_accessibility_macos_src_files
+    ${adaptor_accessibility_dir}/generic/tts-player-factory-generic.cpp
+    ${adaptor_accessibility_dir}/generic/tts-player-impl-generic.cpp
+)
index a0f690e..1b9e11f 100644 (file)
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <dali/integration-api/platform-abstraction.h>
 #include <unistd.h>
+#include "dali/public-api/common/dali-common.h"
 
 // INTERNAL INCLUDES
 #include <dali/integration-api/adaptor-framework/trigger-event-factory.h>
@@ -92,9 +93,8 @@ const unsigned int MAXIMUM_UPDATE_REQUESTS = 2;
 CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions, ThreadMode threadMode )
 : mFpsTracker( environmentOptions ),
   mUpdateStatusLogger( environmentOptions ),
-  mEventThreadSemaphore(),
-  mGraphicsInitializeSemaphore(),
-  mSurfaceSemaphore(),
+  mEventThreadSemaphore(0),
+  mSurfaceSemaphore(0),
   mUpdateRenderThreadWaitCondition(),
   mAdaptorInterfaces( adaptorInterfaces ),
   mPerformanceInterface( adaptorInterfaces.GetPerformanceInterface() ),
@@ -137,11 +137,6 @@ CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalS
   }
 
   mSleepTrigger = TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &CombinedUpdateRenderController::ProcessSleepRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
-
-  // Initialize to 0 so that it just waits if sem_post has not been called
-  sem_init( &mEventThreadSemaphore, 0, 0 );
-  sem_init( &mGraphicsInitializeSemaphore, 0, 0 );
-  sem_init( &mSurfaceSemaphore, 0, 0 );
 }
 
 CombinedUpdateRenderController::~CombinedUpdateRenderController()
@@ -162,6 +157,7 @@ void CombinedUpdateRenderController::Initialize()
   DALI_ASSERT_ALWAYS( ! mUpdateRenderThread );
 
   // Create Update/Render Thread
+  ConditionalWait::ScopedLock lock(mGraphicsInitializeWait);
   mUpdateRenderThread = new pthread_t();
   int error = pthread_create( mUpdateRenderThread, NULL, InternalUpdateRenderThreadEntryFunc, this );
   DALI_ASSERT_ALWAYS( !error && "Return code from pthread_create() when creating UpdateRenderThread" );
@@ -179,13 +175,7 @@ void CombinedUpdateRenderController::Start()
   // Wait until all threads created in Initialise are up and running
   for( unsigned int i = 0; i < CREATED_THREAD_COUNT; ++i )
   {
-    sem_wait( &mEventThreadSemaphore );
-  }
-
-  Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface();
-  if( currentSurface )
-  {
-    currentSurface->StartRender();
+    mEventThreadSemaphore.Acquire();
   }
 
   mRunning = TRUE;
@@ -194,6 +184,12 @@ void CombinedUpdateRenderController::Start()
 
   RunUpdateRenderThread( CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL );
 
+  Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface();
+  if( currentSurface )
+  {
+    currentSurface->StartRender();
+  }
+
   DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Start\n" );
 }
 
@@ -321,7 +317,7 @@ void CombinedUpdateRenderController::ReplaceSurface( Dali::RenderSurfaceInterfac
     }
 
     // Wait until the surface has been replaced
-    sem_wait( &mSurfaceSemaphore );
+    mSurfaceSemaphore.Acquire();
 
     LOG_EVENT( "Surface replaced, event-thread continuing" );
   }
@@ -344,7 +340,7 @@ void CombinedUpdateRenderController::DeleteSurface( Dali::RenderSurfaceInterface
     }
 
     // Wait until the surface has been deleted
-    sem_wait( &mSurfaceSemaphore );
+    mSurfaceSemaphore.Acquire();
 
     LOG_EVENT( "Surface deleted, event-thread continuing" );
   }
@@ -352,6 +348,7 @@ void CombinedUpdateRenderController::DeleteSurface( Dali::RenderSurfaceInterface
 
 void CombinedUpdateRenderController::WaitForGraphicsInitialization()
 {
+  ConditionalWait::ScopedLock lk(mGraphicsInitializeWait);
   LOG_EVENT_TRACE;
 
   if( mUpdateRenderThread )
@@ -359,7 +356,7 @@ void CombinedUpdateRenderController::WaitForGraphicsInitialization()
     LOG_EVENT( "Waiting for graphics initialisation, event-thread blocked" );
 
     // Wait until the graphics has been initialised
-    sem_wait( &mGraphicsInitializeSemaphore );
+    mGraphicsInitializeWait.Wait(lk);
 
     LOG_EVENT( "graphics initialised, event-thread continuing" );
   }
@@ -944,7 +941,7 @@ Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeRep
 void CombinedUpdateRenderController::SurfaceReplaced()
 {
   // Just increment the semaphore
-  sem_post( &mSurfaceSemaphore );
+  mSurfaceSemaphore.Release(1);
 }
 
 Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeDeleted()
@@ -960,7 +957,7 @@ Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeDel
 void CombinedUpdateRenderController::SurfaceDeleted()
 {
   // Just increment the semaphore
-  sem_post( &mSurfaceSemaphore );
+  mSurfaceSemaphore.Release(1);
 }
 
 bool CombinedUpdateRenderController::ShouldSurfaceBeResized()
@@ -982,12 +979,12 @@ void CombinedUpdateRenderController::SurfaceResized()
 void CombinedUpdateRenderController::NotifyThreadInitialised()
 {
   // Just increment the semaphore
-  sem_post( &mEventThreadSemaphore );
+  mEventThreadSemaphore.Release(1);
 }
 
 void CombinedUpdateRenderController::NotifyGraphicsInitialised()
 {
-  sem_post( &mGraphicsInitializeSemaphore );
+  mGraphicsInitializeWait.Notify();
 }
 
 void CombinedUpdateRenderController::AddPerformanceMarker( PerformanceInterface::MarkerType type )
index c87a1a6..8c2da95 100644 (file)
@@ -24,6 +24,7 @@
 #include <atomic>
 #include <stdint.h>
 #include <dali/devel-api/threading/conditional-wait.h>
+#include <dali/devel-api/threading/semaphore.h>
 #include <dali/integration-api/core.h>
 
 // INTERNAL INCLUDES
@@ -343,9 +344,9 @@ private:
   FpsTracker                        mFpsTracker;                       ///< Object that tracks the FPS
   UpdateStatusLogger                mUpdateStatusLogger;               ///< Object that logs the update-status as required.
 
-  sem_t                             mEventThreadSemaphore;             ///< Used by the event thread to ensure all threads have been initialised.
-  sem_t                             mGraphicsInitializeSemaphore;      ///< Used by the render thread to ensure the graphics has been initialised.
-  sem_t                             mSurfaceSemaphore;                 ///< Used by the event thread to ensure the surface has been deleted or replaced.
+  Semaphore<>                       mEventThreadSemaphore;             ///< Used by the event thread to ensure all threads have been initialised, and when replacing the surface.
+  ConditionalWait                   mGraphicsInitializeWait;           ///< Used by the render thread to ensure the graphics has been initialised.
+  Semaphore<>                       mSurfaceSemaphore;                 ///< Used by the event thread to ensure the surface has been deleted or replaced.
 
   ConditionalWait                   mUpdateRenderThreadWaitCondition;  ///< The wait condition for the update-render-thread.
 
index 34b2f41..ed2e8af 100644 (file)
@@ -52,3 +52,9 @@ SET( adaptor_adaptor_component_application_src_files
     ${adaptor_adaptor_dir}/tizen-wayland/component-application.cpp
     ${adaptor_adaptor_dir}/tizen-wayland/component-application-impl.cpp
 )
+
+# module: adaptor, backend: macos
+SET( adaptor_adaptor_macos_src_files
+    ${adaptor_adaptor_dir}/generic/adaptor-impl-generic.cpp
+    ${adaptor_adaptor_dir}/macos/framework-mac.mm
+)
diff --git a/dali/internal/adaptor/macos/framework-mac.mm b/dali/internal/adaptor/macos/framework-mac.mm
new file mode 100644 (file)
index 0000000..4bd637c
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2020 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.
+ *
+ */
+
+#import <Cocoa/Cocoa.h>
+
+#include "extern-definitions.h"
+
+// CLASS HEADER
+#include <dali/internal/adaptor/common/framework.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/system/common/callback-manager.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+
+/// Application Status Enum
+enum
+{
+  APP_CREATE,
+  APP_TERMINATE,
+  APP_PAUSE,
+  APP_RESUME,
+  APP_RESET,
+  APP_LANGUAGE_CHANGE,
+};
+
+} // Unnamed namespace
+
+/**
+ * Impl to hide WindowsSystem data members
+ */
+struct Framework::Impl
+{
+  // Constructor
+
+  Impl(void* data)
+  : mAbortCallBack( nullptr ),
+    mLanguage( "NOT_SUPPORTED" ),
+    mRegion( "NOT_SUPPORTED" )
+  {
+  }
+
+  ~Impl()
+  {
+    delete mAbortCallBack;
+  }
+
+  std::string GetLanguage() const
+  {
+    return mLanguage;
+  }
+
+  std::string GetRegion() const
+  {
+    return mRegion;
+  }
+
+  void SetAbortCallback( CallbackBase *base )
+  {
+    mAbortCallBack = base;
+  }
+
+  bool ExecuteCallback()
+  {
+    if( nullptr != mAbortCallBack )
+    {
+      CallbackBase::Execute( *mAbortCallBack );
+      return true;
+    }
+
+    return false;
+  }
+
+private:
+  // Undefined
+  Impl( const Impl& impl ) = delete;
+
+  // Undefined
+  Impl& operator=( const Impl& impl ) = delete;
+
+private:
+  // Data
+  CallbackBase* mAbortCallBack;
+  std::string mLanguage;
+  std::string mRegion;
+};
+
+Framework::Framework( Framework::Observer& observer, int *argc, char ***argv, Type type )
+: mObserver(observer),
+  mInitialised(false),
+  mPaused(false),
+  mRunning(false),
+  mArgc(argc),
+  mArgv(argv),
+  mBundleName(""),
+  mBundleId(""),
+  mAbortHandler( MakeCallback( this, &Framework::AbortCallback ) ),
+  mImpl(NULL)
+{
+    InitThreads();
+    mImpl = new Impl(this);
+
+    // ensures the NSApp global object is initialized
+    [NSApplication sharedApplication];
+
+    // this is needed for applications without a bundle
+    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+    // make sure we can become the key window
+    [NSApp activateIgnoringOtherApps:YES];
+}
+
+Framework::~Framework()
+{
+  if (mRunning)
+  {
+    Quit();
+  }
+
+  delete mImpl;
+}
+
+void Framework::Run()
+{
+  mRunning = true;
+  AppStatusHandler(APP_CREATE, nullptr);
+  [NSApp run];
+  mRunning = false;
+}
+
+void Framework::Quit()
+{
+  AppStatusHandler(APP_TERMINATE, nullptr);
+}
+
+bool Framework::IsMainLoopRunning()
+{
+  return mRunning;
+}
+
+void Framework::AddAbortCallback( CallbackBase* callback )
+{
+  mImpl->SetAbortCallback( callback );
+}
+
+std::string Framework::GetBundleName() const
+{
+  return mBundleName;
+}
+
+void Framework::SetBundleName(const std::string& name)
+{
+  mBundleName = name;
+}
+
+std::string Framework::GetBundleId() const
+{
+  return mBundleId;
+}
+
+std::string Framework::GetResourcePath()
+{
+  // "DALI_APPLICATION_PACKAGE" is used by macOS specifically to get the already configured Application package path.
+  const char* macEnvironmentVariable = "DALI_APPLICATION_PACKAGE";
+  char* value = getenv( macEnvironmentVariable );
+
+  std::string resourcePath;
+  if ( value != NULL )
+  {
+    resourcePath = value;
+  }
+
+  if( resourcePath.back() != '/' )
+  {
+    resourcePath+="/";
+  }
+
+  return resourcePath;
+}
+
+std::string Framework::GetDataPath()
+{
+  return app_get_data_path();
+}
+
+void Framework::SetBundleId(const std::string& id)
+{
+  mBundleId = id;
+}
+
+void Framework::AbortCallback( )
+{
+  // if an abort call back has been installed run it.
+  if( false == mImpl->ExecuteCallback() )
+  {
+    Quit();
+  }
+}
+
+bool Framework::AppStatusHandler(int type, void *)
+{
+  switch (type)
+  {
+    case APP_CREATE:
+    {
+      mInitialised = true;
+      mObserver.OnInit();
+      break;
+    }
+
+    case APP_RESET:
+      mObserver.OnReset();
+      break;
+
+    case APP_RESUME:
+      mObserver.OnResume();
+      break;
+
+    case APP_TERMINATE:
+      mObserver.OnTerminate();
+      break;
+
+    case APP_PAUSE:
+      mObserver.OnPause();
+      break;
+
+    case APP_LANGUAGE_CHANGE:
+      mObserver.OnLanguageChanged();
+      break;
+
+    default:
+      break;
+  }
+
+  return true;
+}
+
+void Framework::InitThreads()
+{
+}
+
+std::string Framework::GetLanguage() const
+{
+  return mImpl->GetLanguage();
+}
+
+std::string Framework::GetRegion() const
+{
+  return mImpl->GetRegion();
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
index 7ac026a..79af910 100644 (file)
@@ -24,3 +24,7 @@ SET( adaptor_clipboard_windows_src_files
     ${adaptor_clipboard_dir}/generic/clipboard-impl-generic.cpp
 )
 
+# module: clipboard, backend: macos
+SET( adaptor_clipboard_macos_src_files
+    ${adaptor_clipboard_dir}/generic/clipboard-impl-generic.cpp
+)
index 97d4fb9..9bc00e6 100644 (file)
@@ -31,3 +31,8 @@ SET( adaptor_graphics_windows_src_files
     ${adaptor_graphics_dir}/windows-gl/egl-image-extensions.cpp
 )
 
+# module: graphics, backend: macos
+SET( adaptor_graphics_macos_src_files
+    ${adaptor_graphics_dir}/macos/egl-image-extensions.cpp
+)
+
diff --git a/dali/internal/graphics/macos/egl-image-extensions.cpp b/dali/internal/graphics/macos/egl-image-extensions.cpp
new file mode 100644 (file)
index 0000000..671c45a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020 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 <dali/internal/graphics/common/egl-image-extensions.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/gles/egl-implementation.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+EglImageExtensions::EglImageExtensions(EglImplementation* eglImpl)
+: mEglImplementation(eglImpl),
+  mImageKHRInitialized(false),
+  mImageKHRInitializeFailed(false)
+{
+  DALI_ASSERT_ALWAYS( eglImpl && "EGL Implementation not instantiated" );
+}
+
+EglImageExtensions::~EglImageExtensions()
+{
+}
+
+void* EglImageExtensions::CreateImageKHR(EGLClientBuffer clientBuffer)
+{
+  DALI_LOG_ERROR(" does not support CreateImageKHR\n");
+  return NULL;
+}
+
+void EglImageExtensions::DestroyImageKHR(void* eglImageKHR)
+{
+  DALI_LOG_ERROR(" does not support DestroyImageKHR\n");
+}
+
+void EglImageExtensions::TargetTextureKHR(void* eglImageKHR)
+{
+  DALI_LOG_ERROR(" does not support TargetTextureKHR\n");
+}
+
+void EglImageExtensions::InitializeEglImageKHR()
+{
+  DALI_LOG_ERROR(" does not support InitializeEglImageKHR\n");
+}
+
+} // namespace Dali::Internal::Adaptor
index c91ffcf..b5f0894 100644 (file)
@@ -53,3 +53,11 @@ SET( adaptor_imaging_windows_src_files
     ${adaptor_imaging_dir}/windows/native-image-source-factory-win.cpp
     ${adaptor_imaging_dir}/windows/native-image-source-impl-win.cpp
 )
+
+# module: imaging, backend: macos
+SET( adaptor_imaging_macos_src_files
+    ${adaptor_imaging_dir}/common/file-download.cpp
+    ${adaptor_imaging_dir}/macos/native-image-source-factory-mac.cpp
+    ${adaptor_imaging_dir}/macos/native-image-source-impl-mac.cpp
+)
+
diff --git a/dali/internal/imaging/macos/native-image-source-factory-mac.cpp b/dali/internal/imaging/macos/native-image-source-factory-mac.cpp
new file mode 100644 (file)
index 0000000..d905355
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/imaging/macos/native-image-source-factory-mac.h>
+
+// INTERNAL HEADERS
+#include <dali/internal/imaging/macos/native-image-source-impl-mac.h>
+#include <dali/internal/imaging/common/native-image-source-queue-impl.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+std::unique_ptr< NativeImageSource >
+NativeImageSourceFactoryCocoa::CreateNativeImageSource(
+  unsigned int width,
+  unsigned int height,
+  Dali::NativeImageSource::ColorDepth depth,
+  Any nativeImageSource
+)
+{
+  return std::unique_ptr< NativeImageSource >( NativeImageSourceCocoa::New(
+    width,
+    height,
+    depth,
+    nativeImageSource
+  ));
+}
+
+std::unique_ptr< NativeImageSourceQueue >
+NativeImageSourceFactoryCocoa::CreateNativeImageSourceQueue(
+  unsigned int width,
+  unsigned int height,
+  Dali::NativeImageSourceQueue::ColorDepth depth,
+  Any nativeImageSourceQueue
+)
+{
+  return std::unique_ptr< NativeImageSourceQueue >( nullptr );
+}
+
+// this should be created from somewhere
+std::unique_ptr< NativeImageSourceFactory > GetNativeImageSourceFactory()
+{
+  // returns native image source factory
+  return std::unique_ptr< NativeImageSourceFactoryCocoa >( new NativeImageSourceFactoryCocoa() );
+}
+
+} // Dali::Internal::Adaptor
diff --git a/dali/internal/imaging/macos/native-image-source-factory-mac.h b/dali/internal/imaging/macos/native-image-source-factory-mac.h
new file mode 100644 (file)
index 0000000..65f6f8c
--- /dev/null
@@ -0,0 +1,44 @@
+#pragma once
+
+/*
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/imaging/common/native-image-source-factory.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+class NativeImageSourceFactoryCocoa : public NativeImageSourceFactory
+{
+public:
+  std::unique_ptr< NativeImageSource > CreateNativeImageSource(
+    unsigned int width,
+    unsigned int height,
+    Dali::NativeImageSource::ColorDepth depth,
+    Any nativeImageSource
+  ) override;
+
+  std::unique_ptr< NativeImageSourceQueue > CreateNativeImageSourceQueue(
+    unsigned int width,
+    unsigned int height,
+    Dali::NativeImageSourceQueue::ColorDepth depth,
+    Any nativeImageSourceQueue
+  ) override;
+};
+
+} // Dali::Internal::Adaptor
diff --git a/dali/internal/imaging/macos/native-image-source-impl-mac.cpp b/dali/internal/imaging/macos/native-image-source-impl-mac.cpp
new file mode 100644 (file)
index 0000000..385e487
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2020 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 <dali/internal/imaging/macos/native-image-source-impl-mac.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/common/egl-image-extensions.h>
+#include <dali/internal/graphics/gles/egl-graphics.h>
+#include <dali/internal/adaptor/common/adaptor-impl.h>
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+using Dali::Integration::PixelBuffer;
+
+NativeImageSourceCocoa* NativeImageSourceCocoa::New(
+  unsigned int width,
+  unsigned int height,
+  Dali::NativeImageSource::ColorDepth depth,
+  Any nativeImageSource
+)
+{
+  return new NativeImageSourceCocoa( width, height, depth, nativeImageSource );
+}
+
+NativeImageSourceCocoa::NativeImageSourceCocoa(
+  unsigned int width,
+  unsigned int height,
+  Dali::NativeImageSource::ColorDepth depth,
+  Any nativeImageSource
+)
+: mImage(MakeRef<CGImageRef>(nullptr))
+{
+  DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
+  DALI_ASSERT_ALWAYS( nativeImageSource.Empty() );
+
+  CFStringRef colorSpaceName;
+  CGImageAlphaInfo alphaInfo;
+  std::size_t bitsPerPixel;
+
+  switch (depth)
+  {
+    case Dali::NativeImageSource::COLOR_DEPTH_8:
+      colorSpaceName = kCGColorSpaceGenericGray;
+      alphaInfo = kCGImageAlphaNone;
+      bitsPerPixel = 8;
+      break;
+    case Dali::NativeImageSource::COLOR_DEPTH_16:
+      colorSpaceName = kCGColorSpaceSRGB;
+      alphaInfo = kCGImageAlphaNone;
+      bitsPerPixel = 16;
+      break;
+    case Dali::NativeImageSource::COLOR_DEPTH_24:
+      colorSpaceName = kCGColorSpaceSRGB;
+      alphaInfo = kCGImageAlphaNone;
+      bitsPerPixel = 24;
+      break;
+    case Dali::NativeImageSource::COLOR_DEPTH_32:
+    default:
+      colorSpaceName = kCGColorSpaceSRGB;
+      alphaInfo = kCGImageAlphaLast;
+      bitsPerPixel = 32;
+      break;
+  }
+
+  // round to next 16 bytes boundary
+  std::size_t bytesPerRow = width & ~0xf;
+  bytesPerRow = bytesPerRow ? bytesPerRow + 16 : width;
+
+  auto dataProvider = MakeRef(CGDataProviderCreateWithData(nullptr, nullptr, 0, nullptr));
+  auto colorSpace = MakeRef(CGColorSpaceCreateWithName(colorSpaceName));
+  mImage = MakeRef(CGImageCreate(
+    width,
+    height,
+    8,
+    bitsPerPixel,
+    bytesPerRow,
+    colorSpace.get(),
+    alphaInfo,
+    dataProvider.get(),
+    nullptr,
+    true,
+    kCGRenderingIntentDefault
+  ));
+
+  if (mImage)
+  {
+    colorSpace.release();
+    dataProvider.release();
+  }
+
+  DALI_ASSERT_ALWAYS(mImage.get());
+}
+
+NativeImageSourceCocoa::~NativeImageSourceCocoa()
+{
+}
+
+Any NativeImageSourceCocoa::GetNativeImageSource() const
+{
+  return Any();
+}
+
+bool NativeImageSourceCocoa::GetPixels(
+  std::vector<uint8_t>& pixbuf,
+  unsigned& width, unsigned& height,
+  Pixel::Format& pixelFormat
+) const
+{
+  width  = CGImageGetWidth(mImage.get());
+  height = CGImageGetHeight(mImage.get());
+  return true;
+}
+
+void NativeImageSourceCocoa::SetSource( Any source )
+{
+}
+
+bool NativeImageSourceCocoa::IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth )
+{
+  return true;
+}
+
+bool NativeImageSourceCocoa::CreateResource()
+{
+  return false;
+}
+
+void NativeImageSourceCocoa::DestroyResource()
+{
+}
+
+unsigned int NativeImageSourceCocoa::TargetTexture()
+{
+  return 0;
+}
+
+void NativeImageSourceCocoa::PrepareTexture()
+{
+}
+
+const char* NativeImageSourceCocoa::GetCustomFragmentPrefix() const
+{
+  return nullptr;
+}
+
+const char* NativeImageSourceCocoa::GetCustomSamplerTypename() const
+{
+  return nullptr;
+}
+
+int NativeImageSourceCocoa::GetTextureTarget() const
+{
+  return GL_TEXTURE_2D;
+}
+
+Any NativeImageSourceCocoa::GetNativeImageHandle() const
+{
+  return Any(mImage.get());
+}
+
+unsigned int NativeImageSourceCocoa::GetWidth() const
+{
+  return CGImageGetWidth(mImage.get());
+}
+
+unsigned int NativeImageSourceCocoa::GetHeight() const
+{
+  return CGImageGetHeight(mImage.get());
+}
+
+bool NativeImageSourceCocoa::RequiresBlending() const
+{
+  const auto alphaInfo = CGImageGetAlphaInfo(mImage.get());
+  return
+    alphaInfo != kCGImageAlphaNone
+    && alphaInfo != kCGImageAlphaNoneSkipFirst
+    && alphaInfo != kCGImageAlphaNoneSkipLast;
+}
+
+bool NativeImageSourceCocoa::SourceChanged() const
+{
+  return false;
+}
+
+uint8_t* NativeImageSourceCocoa::AcquireBuffer( uint16_t& width, uint16_t& height, uint16_t& stride )
+{
+  return nullptr;
+}
+
+
+bool NativeImageSourceCocoa::ReleaseBuffer()
+{
+  return false;
+}
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/imaging/macos/native-image-source-impl-mac.h b/dali/internal/imaging/macos/native-image-source-impl-mac.h
new file mode 100644 (file)
index 0000000..84ef554
--- /dev/null
@@ -0,0 +1,183 @@
+#pragma once
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/native-image-source.h>
+
+#include <dali/internal/imaging/common/native-image-source-impl.h>
+#include <extern-definitions.h>
+#include <CoreGraphics/CoreGraphics.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+class EglImageExtensions;
+
+/**
+ * Dali internal NativeImageSource.
+ */
+class NativeImageSourceCocoa : public Internal::Adaptor::NativeImageSource
+{
+public:
+
+  /**
+   * Create a new NativeImageSource internally.
+   * Depending on hardware the width and height may have to be a power of two.
+   * @param[in] width The width of the image.
+   * @param[in] height The height of the image.
+   * @param[in] depth color depth of the image.
+   * @param[in] nativeImageSource contains either: pixmap of type Win32 Pixmap , a WinPixmap or is empty
+   * @return A smart-pointer to a newly allocated image.
+   */
+  static NativeImageSourceCocoa* New(
+    unsigned int width,
+    unsigned int height,
+    Dali::NativeImageSource::ColorDepth depth,
+    Any nativeImageSource
+  );
+
+  /**
+   * @copydoc Dali::NativeImageSource::GetNativeImageSource()
+   */
+  Any GetNativeImageSource() const override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::GetPixels()
+   */
+  bool GetPixels(
+    std::vector<unsigned char> &pixbuf,
+    unsigned int &width,
+    unsigned int &height,
+    Pixel::Format& pixelFormat
+  ) const override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::SetSource( Any source )
+   */
+  void SetSource( Any source ) override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::IsColorDepthSupported( ColorDepth colorDepth )
+   */
+  bool IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth ) override;
+
+  /**
+   * destructor
+   */
+  ~NativeImageSourceCocoa() override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::CreateResource()
+   */
+  bool CreateResource() override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::DestroyResource()
+   */
+  void DestroyResource() override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::TargetTexture()
+   */
+  unsigned int TargetTexture() override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::PrepareTexture()
+   */
+  void PrepareTexture() override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::GetWidth()
+   */
+  unsigned int GetWidth() const override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::GetHeight()
+   */
+  unsigned int GetHeight() const override;
+
+  /**
+   * @copydoc Dali::NativeImageSource::RequiresBlending()
+   */
+  bool RequiresBlending() const override;
+
+  /**
+   * @copydoc Dali::NativeImageInterface::GetCustomFragmentPrefix()
+   */
+  const char* GetCustomFragmentPrefix() const override;
+
+  /**
+   * @copydoc Dali::NativeImageInterface::GetCustomSamplerTypename()
+   */
+  const char* GetCustomSamplerTypename() const override;
+
+  /**
+   * @copydoc Dali::NativeImageInterface::GetTextureTarget()
+   */
+  int GetTextureTarget() const override;
+
+  /**
+   * @copydoc Dali::NativeImageInterface::GetNativeImageHandle()
+   */
+  Any GetNativeImageHandle() const override;
+
+  /**
+   * @copydoc Dali::NativeImageInterface::SourceChanged()
+   */
+  bool SourceChanged() const override;
+
+  /**
+   * @copydoc Dali::NativeImageInterface::GetExtension()
+   */
+  NativeImageInterface::Extension* GetNativeImageInterfaceExtension() override
+  {
+    return nullptr;
+  }
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::NativeImageSource::AcquireBuffer()
+   */
+  uint8_t* AcquireBuffer( uint16_t& width, uint16_t& height, uint16_t& stride ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::NativeImageSource::ReleaseBuffer()
+   */
+  bool ReleaseBuffer() override;
+
+private:
+
+  /**
+   * Private constructor; @see NativeImageSource::New()
+   * @param[in] width The width of the image.
+   * @param[in] height The height of the image.
+   * @param[in] colour depth of the image.
+   * @param[in] nativeImageSource contains either: pixmap of type Win32 Pixmap , a WinPixmap or is empty
+   */
+  NativeImageSourceCocoa(
+    unsigned int width,
+    unsigned  int height,
+    Dali::NativeImageSource::ColorDepth depth,
+    Any nativeImageSource
+  );
+
+private:
+  CFRef<CGImageRef> mImage;
+};
+
+} // namespace Dali::Internal::Adaptor
index 3e447ce..f15c23f 100644 (file)
@@ -41,3 +41,11 @@ SET( adaptor_input_windows_src_files
     ${adaptor_input_dir}/windows/key-mapping-win.cpp
     ${adaptor_input_dir}/windows/virtual-keyboard-impl-win.cpp
 )
+
+# module: input, backend: macos
+SET( adaptor_input_macos_src_files
+    ${adaptor_input_dir}/macos/input-method-context-factory-mac.cpp
+    ${adaptor_input_dir}/macos/input-method-context-impl-mac.cpp
+    ${adaptor_input_dir}/macos/key-mapping-mac.cpp
+    ${adaptor_input_dir}/macos/virtual-keyboard-impl-mac.cpp
+)
diff --git a/dali/internal/input/macos/input-method-context-factory-mac.cpp b/dali/internal/input/macos/input-method-context-factory-mac.cpp
new file mode 100644 (file)
index 0000000..5a799c0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ */
+
+#include <memory>
+#include <dali/internal/input/common/input-method-context-factory.h>
+#include <dali/internal/input/macos/input-method-context-impl-mac.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+class InputMethodContext;
+
+namespace InputMethodContextFactory
+{
+
+// InputMethodContext Factory to be implemented by the platform
+InputMethodContextPtr CreateInputMethodContext( Dali::Actor actor )
+{
+  return Dali::Internal::Adaptor::InputMethodContextCocoa::New( actor );
+}
+
+}
+
+}
+
+
+
+}
+}
diff --git a/dali/internal/input/macos/input-method-context-impl-mac.cpp b/dali/internal/input/macos/input-method-context-impl-mac.cpp
new file mode 100644 (file)
index 0000000..ff4fc10
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2020 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 <dali/internal/input/macos/input-method-context-impl-mac.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/events/key-event.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/common/singleton-service.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/key.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/internal/adaptor/common/adaptor-impl.h>
+#include <dali/internal/input/common/key-impl.h>
+#include <dali/internal/input/common/virtual-keyboard-impl.h>
+#include <dali/internal/system/common/locale-utils.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_INPUT_METHOD_CONTEXT" );
+#endif
+}
+
+InputMethodContextPtr InputMethodContextCocoa::New( Dali::Actor actor )
+{
+  InputMethodContextPtr manager;
+
+  if ( actor && Adaptor::IsAvailable() )
+  {
+    manager = new InputMethodContextCocoa( actor );
+  }
+
+  return manager;
+}
+
+void InputMethodContextCocoa::Finalize()
+{
+}
+
+InputMethodContextCocoa::InputMethodContextCocoa( Dali::Actor actor )
+: mIMFCursorPosition( 0 ),
+  mSurroundingText(),
+  mRestoreAfterFocusLost( false ),
+  mIdleCallbackConnected( false )
+{
+
+  actor.OnSceneSignal().Connect( this, &InputMethodContextCocoa::OnStaged );
+}
+
+InputMethodContextCocoa::~InputMethodContextCocoa()
+{
+  Finalize();
+}
+
+void InputMethodContextCocoa::Initialize()
+{
+  ConnectCallbacks();
+}
+
+// Callbacks for predicitive text support.
+void InputMethodContextCocoa::ConnectCallbacks()
+{
+}
+
+void InputMethodContextCocoa::DisconnectCallbacks()
+{
+}
+
+void InputMethodContextCocoa::Activate()
+{
+  // Reset mIdleCallbackConnected
+  mIdleCallbackConnected = false;
+}
+
+void InputMethodContextCocoa::Deactivate()
+{
+  mIdleCallbackConnected = false;
+}
+
+void InputMethodContextCocoa::Reset()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::Reset\n" );
+}
+
+ImfContext* InputMethodContextCocoa::GetContext()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::GetContext\n" );
+
+  return NULL;
+}
+
+bool InputMethodContextCocoa::RestoreAfterFocusLost() const
+{
+  return mRestoreAfterFocusLost;
+}
+
+void InputMethodContextCocoa::SetRestoreAfterFocusLost( bool toggle )
+{
+  mRestoreAfterFocusLost = toggle;
+}
+
+/**
+ * Called when an InputMethodContext Pre-Edit changed event is received.
+ * We are still predicting what the user is typing.  The latest string is what the InputMethodContext module thinks
+ * the user wants to type.
+ */
+void InputMethodContextCocoa::PreEditChanged( void*, ImfContext* imfContext, void* eventInfo )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::PreEditChanged\n" );
+}
+
+void InputMethodContextCocoa::CommitReceived( void*, ImfContext* imfContext, void* eventInfo )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::CommitReceived\n" );
+
+  if ( Dali::Adaptor::IsAvailable() )
+  {
+    const std::string keyString( static_cast<char*>( eventInfo ) );
+
+    Dali::InputMethodContext handle( this );
+    Dali::InputMethodContext::EventData eventData( Dali::InputMethodContext::COMMIT, keyString, 0, 0 );
+    Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, eventData );
+
+    if( callbackData.update )
+    {
+      mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
+
+      NotifyCursorPosition();
+    }
+  }
+}
+
+/**
+ * Called when an InputMethodContext retrieve surround event is received.
+ * Here the InputMethodContext 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.
+ */
+bool InputMethodContextCocoa::RetrieveSurrounding( void* data, ImfContext* imfContext, char** text, int* cursorPosition )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::RetrieveSurrounding\n" );
+
+  Dali::InputMethodContext::EventData imfData( Dali::InputMethodContext::GET_SURROUNDING, std::string(), 0, 0 );
+  Dali::InputMethodContext handle( this );
+  Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, imfData );
+
+  if( callbackData.update )
+  {
+    if( text )
+    {
+      *text = strdup( callbackData.currentText.c_str() );
+    }
+
+    if( cursorPosition )
+    {
+      mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
+      *cursorPosition = mIMFCursorPosition;
+    }
+  }
+
+  return true;
+}
+
+/**
+ * Called when an InputMethodContext delete surrounding event is received.
+ * Here we tell the application that it should delete a certain range.
+ */
+void InputMethodContextCocoa::DeleteSurrounding( void* data, ImfContext* imfContext, void* eventInfo )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::DeleteSurrounding\n" );
+}
+
+void InputMethodContextCocoa::NotifyCursorPosition()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::NotifyCursorPosition\n" );
+}
+
+void InputMethodContextCocoa::SetCursorPosition( unsigned int cursorPosition )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::SetCursorPosition\n" );
+
+  mIMFCursorPosition = static_cast<int>( cursorPosition );
+}
+
+unsigned int InputMethodContextCocoa::GetCursorPosition() const
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::GetCursorPosition\n" );
+
+  return static_cast<unsigned int>( mIMFCursorPosition );
+}
+
+void InputMethodContextCocoa::SetSurroundingText( const std::string& text )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::SetSurroundingText\n" );
+
+  mSurroundingText = text;
+}
+
+const std::string& InputMethodContextCocoa::GetSurroundingText() const
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::GetSurroundingText\n" );
+
+  return mSurroundingText;
+}
+
+void InputMethodContextCocoa::NotifyTextInputMultiLine( bool multiLine )
+{
+}
+
+Dali::InputMethodContext::TextDirection InputMethodContextCocoa::GetTextDirection()
+{
+  Dali::InputMethodContext::TextDirection direction ( Dali::InputMethodContext::LEFT_TO_RIGHT);
+
+  return direction;
+}
+
+Rect<int> InputMethodContextCocoa::GetInputMethodArea()
+{
+  int xPos, yPos, width, height;
+
+  width = height = xPos = yPos = 0;
+
+  return Rect<int>(xPos,yPos,width,height);
+}
+
+void InputMethodContextCocoa::ApplyOptions( const InputMethodOptions& options )
+{
+  using namespace Dali::InputMethod::Category;
+
+  int index;
+
+  if ( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) )
+  {
+  }
+  if ( mOptions.CompareAndSet(BUTTON_ACTION, options, index) )
+  {
+  }
+  if ( mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index) )
+  {
+  }
+  if ( mOptions.CompareAndSet(VARIATION, options, index) )
+  {
+  }
+}
+
+void InputMethodContextCocoa::SetInputPanelData( const std::string& data )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::SetInputPanelData\n" );
+}
+
+void InputMethodContextCocoa::GetInputPanelData( std::string& data )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::GetInputPanelData\n" );
+}
+
+Dali::InputMethodContext::State InputMethodContextCocoa::GetInputPanelState()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::GetInputPanelState\n" );
+  return Dali::InputMethodContext::DEFAULT;
+}
+
+void InputMethodContextCocoa::SetReturnKeyState( bool visible )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::SetReturnKeyState\n" );
+}
+
+void InputMethodContextCocoa::AutoEnableInputPanel( bool enabled )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::AutoEnableInputPanel\n" );
+}
+
+void InputMethodContextCocoa::ShowInputPanel()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::ShowInputPanel\n" );
+}
+
+void InputMethodContextCocoa::HideInputPanel()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::HideInputPanel\n" );
+}
+
+Dali::InputMethodContext::KeyboardType InputMethodContextCocoa::GetKeyboardType()
+{
+  return Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD;
+}
+
+std::string InputMethodContextCocoa::GetInputPanelLocale()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::GetInputPanelLocale\n" );
+
+  std::string locale = "";
+  return locale;
+}
+
+void InputMethodContextCocoa::SetContentMIMETypes( const std::string& mimeTypes )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::SetContentMIMETypes\n" );
+}
+
+bool InputMethodContextCocoa::FilterEventKey( const Dali::KeyEvent& keyEvent )
+{
+  bool eventHandled( false );
+
+  if ( ! KeyLookup::IsDeviceButton( keyEvent.GetKeyName().c_str() ))
+  {
+    //check whether it's key down or key up event
+    if ( keyEvent.GetState() == Dali::KeyEvent::DOWN )
+    {
+      eventHandled = ProcessEventKeyDown( keyEvent );
+    }
+    else if ( keyEvent.GetState() == Dali::KeyEvent::UP )
+    {
+      eventHandled = ProcessEventKeyUp( keyEvent );
+    }
+  }
+
+  return eventHandled;
+}
+
+void InputMethodContextCocoa::SetInputPanelLanguage( Dali::InputMethodContext::InputPanelLanguage language )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::SetInputPanelLanguage\n" );
+}
+
+Dali::InputMethodContext::InputPanelLanguage InputMethodContextCocoa::GetInputPanelLanguage() const
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::GetInputPanelLanguage\n" );
+  return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
+}
+
+void InputMethodContextCocoa::SetInputPanelPosition( unsigned int x, unsigned int y )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::SetInputPanelPosition\n" );
+}
+
+void InputMethodContextCocoa::GetPreeditStyle( Dali::InputMethodContext::PreEditAttributeDataContainer& attrs ) const
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextCocoa::GetPreeditStyle\n" );
+  attrs = mPreeditAttrs;
+}
+
+bool InputMethodContextCocoa::ProcessEventKeyDown( const Dali::KeyEvent& keyEvent )
+{
+  bool eventHandled( false );
+  return eventHandled;
+}
+
+bool InputMethodContextCocoa::ProcessEventKeyUp( const Dali::KeyEvent& keyEvent )
+{
+  bool eventHandled( false );
+  return eventHandled;
+}
+
+void InputMethodContextCocoa::OnStaged( Dali::Actor actor )
+{
+  // Reset
+  Finalize();
+  Initialize();
+}
+
+} // Adaptor
+
+} // Internal
+
+} // Dali
+
diff --git a/dali/internal/input/macos/input-method-context-impl-mac.h b/dali/internal/input/macos/input-method-context-impl-mac.h
new file mode 100644 (file)
index 0000000..7e4b10b
--- /dev/null
@@ -0,0 +1,314 @@
+#pragma once
+
+/*
+ * 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 <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/input-method-context.h>
+#include <dali/internal/input/common/input-method-context-impl.h>
+
+namespace Dali
+{
+
+class RenderSurface;
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+class InputMethodContextCocoa : public Dali::Internal::Adaptor::InputMethodContext, public Dali::ConnectionTracker
+{
+public:
+  /**
+   * @brief Creates a new InputMethodContext handle
+   *
+   * @param[in] actor The actor that uses the new InputMethodContext instance.
+   * @return InputMethodContext pointer
+   */
+  static InputMethodContextPtr New( Dali::Actor actor );
+
+  /**
+   * Constructor
+   * @param[in] win32Window, The window is created by application.
+   */
+  explicit InputMethodContextCocoa( Dali::Actor actor );
+
+public:
+
+  /**
+   * @brief Initializes member data.
+   */
+  void Initialize() override;
+
+  /**
+   * Connect Callbacks required for InputMethodContext.
+   * If you don't connect InputMethodContext callbacks, you can't get the key events.
+   * The events are PreeditChanged, Commit and DeleteSurrounding.
+   */
+  void ConnectCallbacks() override;
+
+  /**
+   * Disconnect Callbacks attached to input method context.
+   */
+  void DisconnectCallbacks() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::Finalize()
+   */
+  void Finalize() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::Activate()
+   */
+  void Activate() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::Deactivate()
+   */
+  void Deactivate() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::Reset()
+   */
+  void Reset() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetContext()
+   */
+  ImfContext* GetContext() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::RestoreAfterFocusLost()
+   */
+  bool RestoreAfterFocusLost() const override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SetRestoreAfterFocusLost()
+   */
+  void SetRestoreAfterFocusLost( bool toggle ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::PreEditChanged()
+   */
+  void PreEditChanged( void* data, ImfContext* imfContext, void* eventInfo ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::NotifyCursorPosition()
+   */
+  void CommitReceived( void* data, ImfContext* imfContext, void* eventInfo ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::NotifyCursorPosition()
+   */
+  bool RetrieveSurrounding( void* data, ImfContext* imfContext, char** text, int* cursorPosition ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::DeleteSurrounding()
+   */
+  void DeleteSurrounding( void* data, ImfContext* imfContext, void* eventInfo ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SendPrivateCommand()
+   */
+  void SendPrivateCommand( void* data, ImfContext* imfContext, void* eventInfo ) override
+  {}
+
+  /**
+   * @copydoc Dali::InputMethodContext::SendCommitContent()
+   */
+  void SendCommitContent( void* data, ImfContext* imfContext, void* eventInfo ) override
+  {}
+
+  // Cursor related
+  /**
+   * @copydoc Dali::InputMethodContext::NotifyCursorPosition()
+   */
+  void NotifyCursorPosition() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SetCursorPosition()
+   */
+  void SetCursorPosition( unsigned int cursorPosition ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetCursorPosition()
+   */
+  unsigned int GetCursorPosition() const override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SetSurroundingText()
+   */
+  void SetSurroundingText( const std::string& text ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetSurroundingText()
+   */
+  const std::string& GetSurroundingText() const override;
+
+  /**
+  * @copydoc Dali::InputMethodContext::NotifyTextInputMultiLine()
+  */
+  void NotifyTextInputMultiLine( bool multiLine ) override;
+
+  /**
+  * @copydoc Dali::InputMethodContext::GetTextDirection()
+  */
+  Dali::InputMethodContext::TextDirection GetTextDirection() override;
+
+  /**
+  * @copydoc Dali::InputMethodContext::GetInputMethodArea()
+  */
+  Dali::Rect<int> GetInputMethodArea() override;
+
+  /**
+  * @copydoc Dali::InputMethodContext::ApplyOptions()
+  */
+  void ApplyOptions( const InputMethodOptions& options ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SetInputPanelData()
+   */
+  void SetInputPanelData( const std::string& data ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetInputPanelData()
+   */
+  void GetInputPanelData( std::string& data ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetInputPanelState()
+   */
+  Dali::InputMethodContext::State GetInputPanelState() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SetReturnKeyState()
+   */
+  void SetReturnKeyState( bool visible ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::AutoEnableInputPanel()
+   */
+  void AutoEnableInputPanel( bool enabled ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::ShowInputPanel()
+   */
+  void ShowInputPanel() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::HideInputPanel()
+   */
+  void HideInputPanel() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetKeyboardType()
+   */
+  Dali::InputMethodContext::KeyboardType GetKeyboardType() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetInputPanelLocale()
+   */
+  std::string GetInputPanelLocale() override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SetContentMIMETypes()
+   */
+  void SetContentMIMETypes( const std::string& mimeTypes ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::FilterEventKey()
+   */
+  bool FilterEventKey( const Dali::KeyEvent& keyEvent ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SetInputPanelLanguage()
+   */
+  void SetInputPanelLanguage( Dali::InputMethodContext::InputPanelLanguage language ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetInputPanelLanguage()
+   */
+  Dali::InputMethodContext::InputPanelLanguage GetInputPanelLanguage() const override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::SetInputPanelPosition()
+   */
+  void SetInputPanelPosition( unsigned int x, unsigned int y ) override;
+
+  /**
+   * @copydoc Dali::InputMethodContext::GetPreeditStyle()
+   */
+  void GetPreeditStyle( Dali::InputMethodContext::PreEditAttributeDataContainer& attrs ) const override;
+
+private:
+
+  /**
+   * @brief Process event key down, whether filter a key to isf.
+   *
+   * @param[in] keyEvent The event key to be handled.
+   * @return Whether the event key is handled.
+   */
+  bool ProcessEventKeyDown( const Dali::KeyEvent& keyEvent );
+
+  /**
+   * @brief Process event key up, whether filter a key to isf.
+   *
+   * @param[in] keyEvent The event key to be handled.
+   * @return Whether the event key is handled.
+   */
+  bool ProcessEventKeyUp( const Dali::KeyEvent& keyEvent );
+
+  /**
+   * Called when the binded actor is added to a window.
+   */
+  void OnStaged( Dali::Actor actor );
+
+public:
+
+  /**
+   * Destructor.
+   */
+  virtual ~InputMethodContextCocoa();
+
+private:
+
+  // Undefined copy constructor
+  InputMethodContextCocoa( const InputMethodContextCocoa& inputMethodContext) = delete;
+
+  // Undefined assignment operator
+  InputMethodContextCocoa& operator=( const InputMethodContextCocoa& inputMethodContext ) = delete;
+
+private:
+  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.
+  InputMethodOptions        mOptions;
+  Dali::InputMethodContext::PreEditAttributeDataContainer mPreeditAttrs; ///< Stores preedit attribute data
+};
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/input/macos/key-mapping-mac.cpp b/dali/internal/input/macos/key-mapping-mac.cpp
new file mode 100644 (file)
index 0000000..4c268cc
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/input/common/key-impl.h>
+
+namespace Dali::Internal::Adaptor::KeyLookup
+{
+
+// matches a DALI_KEY enum, to key name
+KeyLookup KeyLookupTable[]=
+{
+  { "Escape",                DALI_KEY_ESCAPE,                                            false },
+  { "Command",               DALI_KEY_MENU,                                              false },
+  { "Cancel",                DALI_KEY_CANCEL,                                            false },
+  { "Backspace",             DALI_KEY_BACKSPACE,                                         false },
+  { "Up",                    DALI_KEY_CURSOR_UP,                                         false },
+  { "Left",                  DALI_KEY_CURSOR_LEFT,                                       false },
+  { "Right",                 DALI_KEY_CURSOR_RIGHT,                                      false },
+  { "Down",                  DALI_KEY_CURSOR_DOWN,                                       false },
+  { "Shift",                 DALI_KEY_SHIFT_LEFT,                                        false },
+  { "Delete",                static_cast<Dali::KEY>( DevelKey::DALI_KEY_DELETE ),        false },
+  { "Control",               static_cast<Dali::KEY>( DevelKey::DALI_KEY_CONTROL_LEFT ),  false },
+};
+
+const std::size_t KEY_LOOKUP_COUNT = (sizeof( KeyLookupTable ))/ (sizeof( KeyLookup ));
+
+}
diff --git a/dali/internal/input/macos/virtual-keyboard-impl-mac.cpp b/dali/internal/input/macos/virtual-keyboard-impl-mac.cpp
new file mode 100644 (file)
index 0000000..cbe01df
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/input/common/virtual-keyboard-impl.h>
+
+namespace Dali::Internal::Adaptor::VirtualKeyboard
+{
+
+void Show()
+{
+}
+
+void Hide()
+{
+
+}
+
+bool IsVisible()
+{
+  return false;
+}
+
+void ApplySettings( const Property::Map& settingsMap )
+{
+
+}
+
+void EnablePrediction( const bool enable )
+{
+
+}
+
+bool IsPredictionEnabled()
+{
+  return false;
+}
+
+Rect<int> GetSizeAndPosition()
+{
+  Rect<int> ret;
+  return ret;
+}
+
+Dali::VirtualKeyboard::StatusSignalType& StatusChangedSignal()
+{
+  static Dali::VirtualKeyboard::StatusSignalType ret;
+  return ret;
+}
+
+Dali::VirtualKeyboard::KeyboardResizedSignalType& ResizedSignal()
+{
+  static Dali::VirtualKeyboard::KeyboardResizedSignalType ret;
+  return ret;
+}
+
+Dali::VirtualKeyboard::LanguageChangedSignalType& LanguageChangedSignal()
+{
+  static Dali::VirtualKeyboard::LanguageChangedSignalType ret;
+  return ret;
+}
+
+Dali::VirtualKeyboard::TextDirection GetTextDirection()
+{
+  return Dali::VirtualKeyboard::LEFT_TO_RIGHT;
+}
+
+void RotateTo(int angle)
+{
+}
+
+void SetReturnKeyType( const InputMethod::ButtonAction::Type type )
+{
+}
+
+Dali::InputMethod::ButtonAction::Type GetReturnKeyType()
+{
+  return Dali::InputMethod::ButtonAction::DEFAULT;
+}
+
+} // namespace Dali::Internal::Adaptor::VirtualKeyboard
index 2910693..f012cdd 100755 (executable)
 // INTERNAL INCLUDES
 #include <dali/public-api/adaptor-framework/application.h>
 
+#if !defined(_NSIG) && defined(NSIG)
+#define _NSIG NSIG
+#endif
+
 namespace Dali
 {
 namespace Internal
index e898d17..33d241c 100644 (file)
@@ -22,7 +22,6 @@ SET( adaptor_system_common_src_files
     ${adaptor_system_dir}/common/stat-context-manager.cpp
     ${adaptor_system_dir}/common/system-trace.cpp
     ${adaptor_system_dir}/common/thread-controller.cpp
-    ${adaptor_system_dir}/common/time-service.cpp
     ${adaptor_system_dir}/common/update-status-logger.cpp
     ${adaptor_system_dir}/common/widget-application-impl.cpp
 )
@@ -35,6 +34,7 @@ SET( adaptor_system_linux_src_files
     ${adaptor_system_dir}/linux/callback-manager-ecore.cpp
     ${adaptor_system_dir}/linux/file-descriptor-monitor-ecore.cpp
     ${adaptor_system_dir}/generic/shared-file-operations-generic.cpp
+    ${adaptor_system_dir}/common/time-service.cpp
     ${adaptor_system_dir}/linux/timer-impl-ecore.cpp
 )
 
@@ -46,6 +46,7 @@ SET( adaptor_system_tizen_wayland_src_files
     ${adaptor_system_dir}/tizen-wayland/logging-tizen.cpp
     ${adaptor_system_dir}/tizen-wayland/system-settings-tizen.cpp
     ${adaptor_system_dir}/tizen-wayland/widget-application-impl-tizen.cpp
+    ${adaptor_system_dir}/common/time-service.cpp
     ${adaptor_system_dir}/tizen-wayland/widget-controller-tizen.cpp
 )
 
@@ -62,6 +63,7 @@ SET( adaptor_system_ubuntu_x11_src_files
     ${adaptor_system_dir}/ubuntu-x11/logging-x.cpp
     ${adaptor_system_dir}/ubuntu-x11/system-settings-x.cpp
     ${adaptor_system_dir}/ubuntu-x11/widget-application-impl-x.cpp
+    ${adaptor_system_dir}/common/time-service.cpp
     ${adaptor_system_dir}/ubuntu-x11/widget-controller-x.cpp
 )
 
@@ -76,6 +78,7 @@ SET( adaptor_system_android_src_files
     ${adaptor_system_dir}/android/shared-file-operations-android.cpp
     ${adaptor_system_dir}/android/system-settings-android.cpp
     ${adaptor_system_dir}/android/timer-impl-android.cpp
+    ${adaptor_system_dir}/common/time-service.cpp
     ${adaptor_system_dir}/android/widget-application-impl-android.cpp
 )
 
@@ -89,5 +92,20 @@ SET( adaptor_system_windows_src_files
     ${adaptor_system_dir}/windows/trigger-event-factory.cpp
     ${adaptor_system_dir}/windows/logging-win.cpp
     ${adaptor_system_dir}/windows/widget-application-impl-win.cpp
+    ${adaptor_system_dir}/common/time-service.cpp
     ${adaptor_system_dir}/windows/widget-controller-win.cpp
 )
+
+# module: system, backend: macOS
+SET( adaptor_system_macos_src_files
+    ${adaptor_system_dir}/ubuntu-x11/logging-x.cpp
+    ${adaptor_system_dir}/macos/file-descriptor-monitor-macos.cpp
+    ${adaptor_system_dir}/macos/timer-impl-mac.cpp
+    ${adaptor_system_dir}/common/shared-file.cpp
+    ${adaptor_system_dir}/common/trigger-event-factory.cpp
+    ${adaptor_system_dir}/generic/shared-file-operations-generic.cpp
+    ${adaptor_system_dir}/common/time-service.cpp
+    ${adaptor_system_dir}/macos/trigger-event.mm
+    ${adaptor_system_dir}/macos/callback-manager-mac.mm
+    ${adaptor_system_dir}/macos/widget-application-impl-mac.cpp
+)
diff --git a/dali/internal/system/macos/callback-manager-mac.h b/dali/internal/system/macos/callback-manager-mac.h
new file mode 100644 (file)
index 0000000..e55ec96
--- /dev/null
@@ -0,0 +1,81 @@
+#pragma once
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/system/common/callback-manager.h>
+#include <memory>
+
+namespace Dali::Internal::Adaptor
+{
+
+/**
+ * @brief Cocoa Implementation of CallbackManager
+ */
+class CocoaCallbackManager : public CallbackManager
+{
+public:
+  CocoaCallbackManager();
+
+  /**
+     * @copydoc CallbackManager::AddIdleCallback()
+   */
+  bool AddIdleCallback( CallbackBase* callback, bool hasReturnValue ) override;
+
+  /**
+   * @caopydoc CallbackManager::RemoveIdleCallback
+   */
+  void RemoveIdleCallback( CallbackBase* callback ) override;
+
+  /**
+   * @copydoc CallbackManager::ProcessIdle
+   */
+  bool ProcessIdle() override;
+
+  /**
+   * @copydoc CallbackManager::ClearIdleCallbacks
+   */
+  void ClearIdleCallbacks() override;
+
+  /**
+   * @copydoc CallbackManager::AddIdleEntererCallback
+   */
+  bool AddIdleEntererCallback( CallbackBase* callback ) override;
+
+  /**
+   * @copydoc CallbackManager::RemoveIdleEntererCallback
+   */
+  void RemoveIdleEntererCallback( CallbackBase* callback ) override;
+
+  /**
+   * @copydoc CallbackManager::Start
+   */
+  void Start() override;
+
+  /**
+   * @copydoc CallbackManager::Stop
+   */
+  void Stop() override;
+
+  struct Impl;
+
+private:
+  std::unique_ptr<Impl> mImpl;
+  bool mRunning;
+};
+
+}
diff --git a/dali/internal/system/macos/callback-manager-mac.mm b/dali/internal/system/macos/callback-manager-mac.mm
new file mode 100644 (file)
index 0000000..7e892c4
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2020 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.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+#include "extern-definitions.h"
+
+#include "callback-manager-mac.h"
+
+#include <unordered_map>
+#include <optional>
+
+namespace
+{
+NSString *EventName = @"Dali::Internal::Adaptor::CallbackManager";
+}
+
+using Dali::Internal::Adaptor::CocoaCallbackManager;
+
+// This is the observer that processes callback events
+@interface CallbackObserver : NSObject
+- (CallbackObserver *) init;
+- (void) ReceiveCallback:(NSNotification *) aNotification;
+@end
+
+// DaliCallback is the Objective-C object holding the information to execute the callback
+@interface DaliCallback : NSObject
+- (DaliCallback *) initWithImpl:(CocoaCallbackManager::Impl*) impl
+                   withCallback:(Dali::CallbackBase *) callback;
+- (void) ExecuteCallback;
+@end
+
+namespace Dali::Internal::Adaptor
+{
+
+namespace Detail
+{
+// Helper class to implement the callbacks containers
+// The boolean value corresponds to the hasReturnValue parameter
+struct CallbackContainer final : public std::unordered_map<CallbackBase*, bool>
+{
+  using Parent = std::unordered_map<CallbackBase*, bool>;
+  using iterator = Parent::iterator;
+  using const_iterator = Parent::const_iterator;
+  using value_type = Parent::value_type;
+  using key_type = Parent::key_type;
+  using size_type = Parent::size_type;
+
+  ~CallbackContainer() { Clear(); }
+
+  void RemoveCallback(const_iterator item)
+  {
+    delete item->first;
+    erase(item);
+  }
+
+  bool RemoveCallback(CallbackBase *callback)
+  {
+    if (auto it(find(callback)); it != end())
+    {
+      RemoveCallback(it);
+      return true;
+    }
+
+    return false;
+  }
+
+  void Clear()
+  {
+    for (auto [cb, dummy]: *this)
+    {
+      delete cb;
+    }
+
+    clear();
+  }
+
+  // Execute the callback if it is present. The first item in the
+  // return value tells either the callback was executed or not.
+  // The second item gives the return value of the callback itself,
+  // if any.
+  std::pair<const_iterator, std::optional<bool>>
+  Execute(CallbackBase *callback) const
+  {
+    std::optional<bool> retValue;
+
+    auto it(find(callback));
+    if (it != end())
+    {
+      retValue = Execute(it);
+    }
+
+    return std::make_pair(it, retValue);
+  }
+
+  std::optional<bool> Execute(const_iterator it) const
+  {
+    auto [callback, hasReturnValue] = *it;
+    if (hasReturnValue)
+    {
+      return CallbackBase::ExecuteReturn<bool>(*callback);
+    }
+    else
+    {
+      CallbackBase::Execute(*callback);
+    }
+
+    return std::optional<bool>();
+  }
+};
+}
+
+// Internal implementation of the CallbackManager
+struct CocoaCallbackManager::Impl final
+{
+  CFRunLoopObserverContext mObserverContext;
+
+  Detail::CallbackContainer mCallbacks, mIdleEntererCallbacks;
+  CFRef<CFRunLoopObserverRef> mIdleObserver;
+  CallbackObserver *mObserver;
+
+  Impl();
+  ~Impl();
+
+  Impl(const Impl &) = delete;
+  Impl &operator=(const Impl&) = delete;
+  Impl(const Impl &&) = delete;
+  Impl &operator=(const Impl&&) = delete;
+
+  bool ProcessIdle();
+  void EnqueueNotification(DaliCallback *callback) const;
+  inline bool AddIdleEntererCallback(CallbackBase *callback);
+  bool AddIdleCallback(CallbackBase *callback, bool hasReturnValue);
+
+private:
+  static void IdleEnterObserverCallback(
+    CFRunLoopObserverRef observer,
+    CFRunLoopActivity activity,
+    void *info
+  );
+};
+
+CocoaCallbackManager::Impl::Impl()
+  : mObserverContext{0, this, nullptr, nullptr, 0}
+  // mIdleObserver is configured to receive a notification
+  // when to run loop is about to sleep
+  , mIdleObserver(MakeRef(CFRunLoopObserverCreate(
+      kCFAllocatorDefault,
+      kCFRunLoopBeforeWaiting,
+      true,
+      0,
+      IdleEnterObserverCallback,
+      &mObserverContext)))
+{
+  CFRunLoopAddObserver(CFRunLoopGetMain(), mIdleObserver.get(), kCFRunLoopCommonModes);
+  mObserver = [[CallbackObserver alloc] init];
+}
+
+CocoaCallbackManager::Impl::~Impl()
+{
+  CFRunLoopRemoveObserver(CFRunLoopGetMain(), mIdleObserver.get(), kCFRunLoopCommonModes);
+  auto *center = [NSNotificationCenter defaultCenter];
+  [center removeObserver:mObserver name:EventName object:nil];
+}
+
+bool CocoaCallbackManager::Impl::ProcessIdle()
+{
+  auto ret = !mCallbacks.empty();
+  for (auto it(cbegin(mCallbacks)), e(cend(mCallbacks)); it != e; ++it)
+  {
+    if (!mCallbacks.Execute(it).value_or(false))
+    {
+      mCallbacks.RemoveCallback(it);
+    }
+  }
+
+  return ret;
+}
+
+void CocoaCallbackManager::Impl::EnqueueNotification(DaliCallback *callback) const
+{
+  auto *notification = [NSNotification notificationWithName:EventName object:callback];
+  auto *queue = [NSNotificationQueue defaultQueue];
+  [queue enqueueNotification:notification postingStyle:NSPostWhenIdle coalesceMask:0 forModes:nil];
+}
+
+bool CocoaCallbackManager::Impl::AddIdleEntererCallback(CallbackBase *callback)
+{
+  return mIdleEntererCallbacks.emplace(callback, true).second;
+}
+
+void CocoaCallbackManager::Impl::IdleEnterObserverCallback(
+  CFRunLoopObserverRef observer,
+  CFRunLoopActivity activity,
+  void *info
+)
+{
+  auto *pImpl = reinterpret_cast<Impl*>(info);
+
+  for (auto it(cbegin(pImpl->mIdleEntererCallbacks)),
+      e(cend(pImpl->mIdleEntererCallbacks)); it != e; ++it)
+  {
+    if (!pImpl->mIdleEntererCallbacks.Execute(it).value_or(false))
+    {
+      pImpl->mIdleEntererCallbacks.RemoveCallback(it);
+    }
+  }
+}
+
+bool CocoaCallbackManager::Impl::AddIdleCallback(
+    CallbackBase *callback, bool hasReturnValue)
+{
+  if (mCallbacks.emplace(callback, hasReturnValue).second)
+  {
+    auto *daliCallback = [[DaliCallback alloc] initWithImpl:this
+                                               withCallback:callback];
+    EnqueueNotification(daliCallback);
+    return true;
+  }
+
+  return false;
+}
+
+// Creates a concrete interface for CallbackManager
+CallbackManager* CallbackManager::New()
+{
+  return new CocoaCallbackManager;
+}
+
+CocoaCallbackManager::CocoaCallbackManager()
+  : mImpl(std::make_unique<CocoaCallbackManager::Impl>())
+  , mRunning(false)
+{
+}
+
+bool CocoaCallbackManager::AddIdleCallback(CallbackBase *callback, bool hasReturnValue)
+{
+  return mRunning && mImpl->AddIdleCallback(callback, hasReturnValue);
+}
+
+void CocoaCallbackManager::RemoveIdleCallback(CallbackBase *callback)
+{
+  mImpl->mCallbacks.RemoveCallback(callback);
+}
+
+bool CocoaCallbackManager::ProcessIdle()
+{
+  return mImpl->ProcessIdle();
+}
+
+void CocoaCallbackManager::ClearIdleCallbacks()
+{
+  mImpl->mCallbacks.Clear();
+}
+
+bool CocoaCallbackManager::AddIdleEntererCallback(CallbackBase* callback)
+{
+  return mRunning && mImpl->AddIdleEntererCallback(callback);;
+}
+
+void CocoaCallbackManager::RemoveIdleEntererCallback(CallbackBase* callback)
+{
+  mImpl->mIdleEntererCallbacks.RemoveCallback(callback);
+}
+
+void CocoaCallbackManager::Start()
+{
+  DALI_ASSERT_DEBUG( mRunning == false );
+  mRunning = true;
+}
+
+void CocoaCallbackManager::Stop()
+{
+  DALI_ASSERT_DEBUG( mRunning == true );
+  mRunning = false;
+}
+
+}
+
+@implementation DaliCallback
+{
+  CocoaCallbackManager::Impl *mImpl;
+  Dali::CallbackBase *mCallback;
+}
+
+- (DaliCallback *) initWithImpl:(CocoaCallbackManager::Impl *) impl
+                   withCallback:(Dali::CallbackBase *) callback
+{
+  self = [super init];
+  if (self)
+  {
+    mImpl = impl;
+    mCallback = callback;
+  }
+  return self;
+}
+
+- (void) ExecuteCallback
+{
+  // Look for the callback inside the list.
+  // If it is not there, then it was either called by ProcessIdle
+  // or was removed by RemoveCallback.
+  if (auto [iter, shouldKeep] = mImpl->mCallbacks.Execute(mCallback);
+      iter != mImpl->mCallbacks.end())
+  {
+    if (!shouldKeep.value_or(false))
+    {
+      mImpl->mCallbacks.RemoveCallback(iter);
+    }
+    else
+    {
+      mImpl->EnqueueNotification(self);
+    }
+  }
+}
+@end
+
+@implementation CallbackObserver
+- (CallbackObserver *) init
+{
+  self = [super init];
+  if (self)
+  {
+    auto *center = [NSNotificationCenter defaultCenter];
+    [center addObserver:self
+               selector:@selector(ReceiveCallback:)
+                   name:EventName
+                 object:nil];
+  }
+  return self;
+}
+
+- (void) ReceiveCallback:(NSNotification *)aNotification
+{
+  DaliCallback *callback = [aNotification object];
+  [callback ExecuteCallback];
+}
+@end
diff --git a/dali/internal/system/macos/file-descriptor-monitor-macos.cpp b/dali/internal/system/macos/file-descriptor-monitor-macos.cpp
new file mode 100644 (file)
index 0000000..75d5a39
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020 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 <dali/internal/system/common/file-descriptor-monitor.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+FileDescriptorMonitor::FileDescriptorMonitor(int fileDescriptor, CallbackBase* callback, int eventBitmask)
+{
+  DALI_LOG_WARNING("Implementation missing for macOS");
+}
+
+FileDescriptorMonitor::~FileDescriptorMonitor()
+{}
+
+} // Dali::Internal::Adaptor
diff --git a/dali/internal/system/macos/timer-impl-mac.cpp b/dali/internal/system/macos/timer-impl-mac.cpp
new file mode 100644 (file)
index 0000000..d3dfd3b
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2020 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 <dali/internal/system/common/timer-impl.h>
+#include "extern-definitions.h"
+
+namespace Dali::Internal::Adaptor
+{
+
+
+/**
+ * Struct to hide away macOS implementation details
+ */
+struct Timer::Impl
+{
+  Impl(Timer *parent, unsigned int milliSec)
+    : mTimer(CreateTimer(parent, milliSec)) {}
+
+  ~Impl() { Stop(); }
+
+  static void TimerProc(CFRunLoopTimerRef timer, void *info);
+
+  void Start();
+  void Stop();
+  void Reset(Timer *parent, unsigned int milliSec);
+
+  unsigned int GetInterval() const noexcept
+  {
+    return CFRunLoopTimerGetInterval(mTimer.get()) * 1000.0;
+  }
+
+  bool IsRunning() const noexcept
+  {
+    return CFRunLoopTimerIsValid(mTimer.get());
+  }
+
+private:
+  CFRef<CFRunLoopTimerRef> CreateTimer(Timer *parent, unsigned int milliSec);
+
+  CFRef<CFRunLoopTimerRef> mTimer;
+};
+
+void Timer::Impl::TimerProc(CFRunLoopTimerRef timer, void *info)
+{
+  auto *pTimer = static_cast<Timer*>(info);
+  pTimer->Tick();
+}
+
+void Timer::Impl::Start()
+{
+  if (!IsRunning())
+  {
+    auto runLoop = CFRunLoopGetMain();
+    CFRunLoopAddTimer(runLoop, mTimer.get(), kCFRunLoopDefaultMode);
+  }
+}
+
+void Timer::Impl::Stop()
+{
+  if (IsRunning())
+  {
+    CFRunLoopTimerContext context;
+    CFRunLoopTimerGetContext(mTimer.get(), &context);
+    const auto interval = CFRunLoopTimerGetInterval(mTimer.get());
+    CFRunLoopTimerInvalidate(mTimer.get());
+
+    // After we invalidate the timer, we can't reuse it, so we create
+    // a new timer for case the user calls Start again
+    const auto fireDate = CFAbsoluteTimeGetCurrent() + interval;
+    mTimer.reset(CFRunLoopTimerCreate(
+      kCFAllocatorDefault,
+      fireDate,
+      interval,
+      0,
+      0,
+      TimerProc,
+      &context
+    ));
+  }
+}
+
+void Timer::Impl::Reset(Timer *parent, unsigned int milliSec)
+{
+  Stop();
+  mTimer = CreateTimer(parent, milliSec);
+  Start();
+}
+
+CFRef<CFRunLoopTimerRef>
+Timer::Impl::CreateTimer(Timer *parent, unsigned int milliSec)
+{
+  const auto interval = static_cast<CFAbsoluteTime>(milliSec) / 1000;
+  const auto fireDate = CFAbsoluteTimeGetCurrent() + interval;
+  CFRunLoopTimerContext context =
+  {
+    .version = 0,
+    .info = parent,
+    .retain = nullptr,
+    .release = nullptr,
+  };
+
+  return MakeRef(CFRunLoopTimerCreate(
+    kCFAllocatorDefault,
+    fireDate, interval,
+    0,
+    0,
+    TimerProc,
+    &context
+  ));
+}
+
+TimerPtr Timer::New( unsigned int milliSec )
+{
+  return new Timer( milliSec );
+}
+
+Timer::Timer( unsigned int milliSec )
+: mImpl(new Impl(this, milliSec))
+{
+}
+
+Timer::~Timer()
+{
+  // stop timers
+  Stop();
+
+  delete mImpl;
+  mImpl = NULL;
+}
+
+void Timer::Start()
+{
+  mImpl->Start();
+}
+
+void Timer::Stop()
+{
+  mImpl->Stop();
+}
+
+void Timer::Pause()
+{
+
+}
+
+void Timer::Resume()
+{
+
+}
+
+void Timer::SetInterval( unsigned int interval, bool restart )
+{
+  mImpl->Reset(this, interval);
+}
+
+unsigned int Timer::GetInterval() const
+{
+  return mImpl->GetInterval();
+}
+
+bool Timer::Tick()
+{
+  // Guard against destruction during signal emission
+  Dali::Timer handle( this );
+
+  bool retVal( false );
+
+  // Override with new signal if used
+  if( !mTickSignal.Empty() )
+  {
+    retVal = mTickSignal.Emit();
+
+    // Timer stops if return value is false
+    if (retVal == false)
+    {
+      Stop();
+    }
+    else
+    {
+      retVal = true;   // continue emission
+    }
+  }
+  else // no callbacks registered
+  {
+    // periodic timer is started but nobody listens, continue
+    retVal = true;
+  }
+
+  return retVal;
+}
+
+Dali::Timer::TimerSignalType& Timer::TickSignal()
+{
+  return mTickSignal;
+}
+
+bool Timer::IsRunning() const
+{
+  return mImpl->IsRunning();
+}
+
+} // namespace Dali::Internal::Adaptor
+
diff --git a/dali/internal/system/macos/trigger-event.h b/dali/internal/system/macos/trigger-event.h
new file mode 100644 (file)
index 0000000..9f80d4d
--- /dev/null
@@ -0,0 +1,68 @@
+#pragma once
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/signals/callback.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-adaptor-common.h>
+#include <dali/integration-api/adaptor-framework/trigger-event-interface.h>
+
+#include <memory>
+
+namespace Dali::Internal::Adaptor
+{
+
+class TriggerEvent : public TriggerEventInterface
+{
+public:
+
+  /**
+   * Constructor
+   * Creates an event file descriptor and starts a GSource which reads from the file
+   * descriptor when there is data.
+   *
+   * @param[in] callback The callback to call
+   * @param[in] options Trigger event options.
+   * @note The ownership of callback is taken by this class.
+   */
+  TriggerEvent( CallbackBase* callback, TriggerEventInterface::Options options );
+
+  /**
+   * Triggers the event.
+   *
+   * This can be called from one thread in order to wake up another thread.
+   */
+  void Trigger() override;
+
+  struct Impl;
+
+private:
+
+  /**
+   * @brief Called when our event file descriptor has been written to.
+   * @param[in] eventBitMask bit mask of events that occured on the file descriptor
+   */
+  void Triggered();
+
+  std::unique_ptr<CallbackBase> mCallback;
+  std::unique_ptr<Impl> mImpl;
+};
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/system/macos/trigger-event.mm b/dali/internal/system/macos/trigger-event.mm
new file mode 100644 (file)
index 0000000..89b31d1
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2020 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.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#include <atomic>
+#include <string>
+#include <sstream>
+#include <type_traits>
+#include "trigger-event.h"
+
+namespace
+{
+const char *EventName = "Dali::Internal::Adaptor::Triggerevent_";
+}
+
+@interface NotificationObserver : NSObject
+
+-(NotificationObserver *) initTriggerImpl:(Dali::Internal::Adaptor::TriggerEvent::Impl *) impl;
+
+@end
+
+namespace Dali::Internal::Adaptor
+{
+
+struct TriggerEvent::Impl final
+{
+  std::unique_ptr<CallbackBase> mCallback;
+  NotificationObserver *mReceiver;
+  NSString *mName;
+  TriggerEventInterface::Options mOptions;
+
+  Impl(CallbackBase *callback, TriggerEventInterface::Options options)
+    : mCallback(callback), mOptions(options)
+  {
+    const auto myId = mNameId.fetch_add(1, std::memory_order_relaxed);
+
+    std::stringstream ss;
+    ss << EventName << myId;
+    mName = [NSString stringWithUTF8String:ss.str().c_str()];
+
+    mReceiver = [[NotificationObserver alloc] initTriggerImpl:this];
+  }
+
+  Impl(Impl &&) = delete;
+  Impl &operator=(Impl &&) = delete;
+
+  ~Impl()
+  {
+    auto *center = [NSNotificationCenter defaultCenter];
+    [center removeObserver:mReceiver];
+  }
+
+  void Trigged()
+  {
+    CallbackBase::Execute( *mCallback );
+  }
+
+private:
+  // This is incremented each time the class is instatiated to guarantee
+  // an unique notification id
+  static std::atomic_uint64_t mNameId;
+};
+
+std::atomic<uint64_t> TriggerEvent::Impl::mNameId{0};
+
+TriggerEvent::TriggerEvent(CallbackBase *callback, TriggerEventInterface::Options options)
+  : mCallback(callback)
+  , mImpl(std::make_unique<Impl>(MakeCallback(this, &TriggerEvent::Triggered), options))
+{
+}
+
+void TriggerEvent::Trigger()
+{
+  auto center = [NSDistributedNotificationCenter defaultCenter];
+
+  // Post a notification to the notification center
+  // The run loop will pop the queue and call the notification center
+  [center postNotificationName:mImpl->mName object:nil];
+}
+
+void TriggerEvent::Triggered()
+{
+  CallbackBase::Execute(*mCallback);
+
+  if (mImpl->mOptions == TriggerEventInterface::DELETE_AFTER_TRIGGER)
+  {
+    delete this;
+  }
+}
+
+}
+
+@implementation NotificationObserver
+{
+  Dali::Internal::Adaptor::TriggerEvent::Impl *mImpl;
+}
+
+-(void) ReceiveNotification: (NSNotification *) aNotification
+{
+  mImpl->Trigged();
+}
+
+-(NotificationObserver *) initTriggerImpl:(Dali::Internal::Adaptor::TriggerEvent::Impl *) impl;
+{
+  self = [super init];
+  if (self)
+  {
+    mImpl = impl;
+    auto center = [NSDistributedNotificationCenter defaultCenter];
+    [center addObserver:self
+               selector:@selector(ReceiveNotification:)
+                   name:impl->mName
+                 object:nil
+     suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
+  }
+
+  return self;
+}
+
+@end
diff --git a/dali/internal/system/macos/widget-application-impl-mac.cpp b/dali/internal/system/macos/widget-application-impl-mac.cpp
new file mode 100644 (file)
index 0000000..cecf303
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/system/macos/widget-application-impl-mac.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+WidgetApplicationPtr WidgetApplicationCocoa::New(
+  int* argc,
+  char **argv[],
+  const std::string& stylesheet)
+{
+  return new WidgetApplicationCocoa(argc, argv, stylesheet );
+}
+
+WidgetApplicationCocoa::WidgetApplicationCocoa(
+  int* argc,
+  char** argv[],
+  const std::string& stylesheet
+)
+: WidgetApplication(argc, argv, stylesheet)
+{
+  DALI_LOG_ERROR("WidgetApplication is not implemented in MACOS profile.\n");
+}
+
+WidgetApplicationCocoa::~WidgetApplicationCocoa()
+{
+}
+
+void WidgetApplicationCocoa::RegisterWidgetCreatingFunction(
+  const std::string& widgetName,
+  Dali::WidgetApplication::CreateWidgetFunction createFunction
+)
+{
+}
+
+// factory function, must be implemented
+namespace WidgetApplicationFactory
+{
+/**
+ * Create a new widget application
+ * @param[in]  argc         A pointer to the number of arguments
+ * @param[in]  argv         A pointer to the argument list
+ * @param[in]  stylesheet   The path to user defined theme file
+ */
+WidgetApplicationPtr Create( int* argc, char **argv[], const std::string& stylesheet )
+{
+  return WidgetApplicationCocoa::New( argc, argv, stylesheet );
+}
+
+} // namespace Factory
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/system/macos/widget-application-impl-mac.h b/dali/internal/system/macos/widget-application-impl-mac.h
new file mode 100644 (file)
index 0000000..a126df3
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef DALI_INTERNAL_WIDGET_APPLICATION_IMPL_WIN_H
+#define DALI_INTERNAL_WIDGET_APPLICATION_IMPL_WIN_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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/adaptor/common/application-impl.h>
+#include <dali/internal/system/common//widget-application-impl.h>
+#include <dali/public-api/adaptor-framework/widget-application.h>
+
+namespace Dali
+{
+class Widget;
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * Implementation of the WidgetApplicationCocoa class.
+ */
+class WidgetApplicationCocoa : public WidgetApplication
+{
+public:
+
+  typedef std::pair<
+    const std::string,
+    Dali::WidgetApplication::CreateWidgetFunction
+  > CreateWidgetFunctionPair;
+
+  typedef std::vector< CreateWidgetFunctionPair > CreateWidgetFunctionContainer;
+
+  /**
+   * Create a new widget application
+   * @param[in]  argc         A pointer to the number of arguments
+   * @param[in]  argv         A pointer to the argument list
+   * @param[in]  stylesheet   The path to user defined theme file
+   */
+  static WidgetApplicationPtr New(
+    int* argc,
+    char **argv[],
+    const std::string& stylesheet
+  );
+
+public:
+
+  /**
+   * @copydoc Dali::WidgetApplication::RegisterWidgetCreator()
+   */
+  void RegisterWidgetCreatingFunction(
+    const std::string& widgetName,
+    Dali::WidgetApplication::CreateWidgetFunction createFunction
+  ) override;
+
+protected:
+
+  /**
+   * Private Constructor
+   * @param[in]  argc         A pointer to the number of arguments
+   * @param[in]  argv         A pointer to the argument list
+   * @param[in]  stylesheet   The path to user defined theme file
+   */
+  WidgetApplicationCocoa( int* argc, char **argv[], const std::string& stylesheet );
+
+  /**
+   * Destructor
+   */
+  virtual ~WidgetApplicationCocoa();
+
+  WidgetApplicationCocoa(const Application&) = delete;
+  WidgetApplicationCocoa& operator=(Application&) = delete;
+};
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_WIDGET_APPLICATION_IMPL_UBUNTU_H
index 4e82a54..eec3695 100755 (executable)
@@ -19,7 +19,7 @@
 #include <dali/internal/text/text-abstraction/font-client-impl.h>
 
 // EXTERNAL INCLUDES
-#if !(defined(DALI_PROFILE_UBUNTU) || defined(ANDROID) || defined(WIN32))
+#if !(defined(DALI_PROFILE_UBUNTU) || defined(ANDROID) || defined(WIN32) || defined(__APPLE__))
 #include <vconf.h>
 #endif
 
@@ -128,7 +128,7 @@ int FontClient::GetDefaultFontSize()
 {
   int fontSize( -1 );
 
-#if !(defined(DALI_PROFILE_UBUNTU) || defined(ANDROID) || defined(WIN32))
+#if !(defined(DALI_PROFILE_UBUNTU) || defined(ANDROID) || defined(WIN32) || defined(__APPLE__))
   vconf_get_int( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, &fontSize );
 #endif
 
index 113931a..5adf76f 100755 (executable)
@@ -32,6 +32,8 @@
 
 // EXTERNAL INCLUDES
 #include <fontconfig/fontconfig.h>
+#include <algorithm>
+#include <iterator>
 
 namespace
 {
@@ -841,6 +843,21 @@ FontId FontClient::Plugin::FindFallbackFont( Character charcode,
     characterSetList = new CharacterSetList;
 
     SetFontList( fontDescription, *fontList, *characterSetList );
+#ifdef __APPLE__
+    FontDescription appleColorEmoji;
+    appleColorEmoji.family = "Apple Color Emoji";
+    appleColorEmoji.width = fontDescription.width;
+    appleColorEmoji.weight = fontDescription.weight;
+    appleColorEmoji.slant = fontDescription.slant;
+    FontList emojiFontList;
+    CharacterSetList emojiCharSetList;
+    SetFontList(appleColorEmoji, emojiFontList, emojiCharSetList);
+
+    std::move(fontList->begin(), fontList->end(), std::back_inserter(emojiFontList));
+    emojiCharSetList.Insert(emojiCharSetList.End(), characterSetList->Begin(), characterSetList->End());
+    *fontList = std::move(emojiFontList);
+    *characterSetList = std::move(emojiCharSetList);
+#endif
 
     // Add the font-list to the cache.
     mFallbackCache.push_back( std::move( FallbackCacheItem( std::move( fontDescription ), fontList, characterSetList ) ) );
index c058c63..8e2d55d 100644 (file)
@@ -343,6 +343,11 @@ bool WebEngine::SendKeyEvent( const Dali::KeyEvent& event )
   return mPlugin->SendKeyEvent( event );
 }
 
+void WebEngine::SetFocus( bool focused )
+{
+  mPlugin->SetFocus( focused );
+}
+
 Dali::WebEnginePlugin::WebEnginePageLoadSignalType& WebEngine::PageLoadStartedSignal()
 {
   return mPlugin->PageLoadStartedSignal();
@@ -362,3 +367,4 @@ Dali::WebEnginePlugin::WebEnginePageLoadErrorSignalType& WebEngine::PageLoadErro
 } // namespace Internal;
 } // namespace Dali;
 
+
old mode 100644 (file)
new mode 100755 (executable)
index 19d93f3..a9a9928
@@ -233,6 +233,11 @@ public:
   bool SendKeyEvent( const Dali::KeyEvent& event );
 
   /**
+   * @copydoc Dali::WebEngine::SetFocus()
+   */
+  void SetFocus( bool focused );
+
+  /**
    * @copydoc Dali::WebEngine::PageLoadStartedSignal()
    */
   Dali::WebEnginePlugin::WebEnginePageLoadSignalType& PageLoadStartedSignal();
index d3a73ac..4f7b234 100644 (file)
@@ -66,3 +66,14 @@ SET( adaptor_window_system_windows_src_files
     ${adaptor_window_system_dir}/windows/window-factory-win.cpp
     ${adaptor_window_system_dir}/windows/window-system-win.cpp
 )
+
+# module: window-system, backend: macos
+SET( adaptor_window_system_macos_src_files
+    ${adaptor_window_system_dir}/macos/display-connection-factory-mac.cpp
+    ${adaptor_window_system_dir}/macos/display-connection-impl-mac.cpp
+    ${adaptor_window_system_dir}/macos/window-render-surface-cocoa.cpp
+    ${adaptor_window_system_dir}/macos/window-system-mac.mm
+    ${adaptor_window_system_dir}/macos/window-base-mac.mm
+    ${adaptor_window_system_dir}/macos/window-factory-mac.cpp
+    ${adaptor_window_system_dir}/macos/render-surface-factory-mac.cpp
+)
diff --git a/dali/internal/window-system/macos/display-connection-factory-mac.cpp b/dali/internal/window-system/macos/display-connection-factory-mac.cpp
new file mode 100644 (file)
index 0000000..14e95d9
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/window-system/macos/display-connection-factory-mac.h>
+#include <dali/internal/window-system/macos/display-connection-impl-mac.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+std::unique_ptr<DisplayConnection>
+DisplayConnectionFactoryCocoa::CreateDisplayConnection()
+{
+  return Utils::MakeUnique<DisplayConnectionCocoa>();
+}
+
+std::unique_ptr<DisplayConnectionFactory>
+GetDisplayConnectionFactory()
+{
+  return Utils::MakeUnique<DisplayConnectionFactoryCocoa>();
+}
+
+}
diff --git a/dali/internal/window-system/macos/display-connection-factory-mac.h b/dali/internal/window-system/macos/display-connection-factory-mac.h
new file mode 100644 (file)
index 0000000..2892af2
--- /dev/null
@@ -0,0 +1,32 @@
+#pragma once
+
+/*
+ * 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.
+ *
+ */
+
+#include <dali/internal/window-system/common/display-connection-factory.h>
+#include <dali/internal/window-system/common/display-utils.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+class DisplayConnectionFactoryCocoa : public DisplayConnectionFactory
+{
+public:
+  std::unique_ptr<DisplayConnection> CreateDisplayConnection() override;
+};
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/display-connection-impl-mac.cpp b/dali/internal/window-system/macos/display-connection-impl-mac.cpp
new file mode 100644 (file)
index 0000000..f8488e4
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2020 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 <EGL/egl.h>
+#include <dali/internal/window-system/macos/display-connection-impl-mac.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/gles/egl-graphics.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+DisplayConnection* DisplayConnectionCocoa::New()
+{
+  return new DisplayConnectionCocoa();
+}
+
+DisplayConnectionCocoa::DisplayConnectionCocoa()
+: mGraphics(nullptr)
+{
+}
+
+DisplayConnectionCocoa::~DisplayConnectionCocoa()
+{
+}
+
+Any DisplayConnectionCocoa::GetDisplay()
+{
+  return EGL_DEFAULT_DISPLAY;
+}
+
+void DisplayConnectionCocoa::ConsumeEvents()
+{
+}
+
+bool DisplayConnectionCocoa::InitializeEgl(EglInterface& egl)
+{
+  EglImplementation& eglImpl = static_cast<EglImplementation&>( egl );
+
+  if(!eglImpl.InitializeGles(EGL_DEFAULT_DISPLAY))
+  {
+    DALI_LOG_ERROR( "Failed to initialize GLES.\n" );
+    return false;
+  }
+
+  return true;
+}
+
+bool DisplayConnectionCocoa::InitializeGraphics()
+{
+  auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
+  EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+
+  if(!eglImpl.InitializeGles(EGL_DEFAULT_DISPLAY))
+  {
+    DALI_LOG_ERROR( "Failed to initialize GLES.\n" );
+    return false;
+  }
+
+  return true;
+}
+
+void DisplayConnectionCocoa::SetSurfaceType( Dali::RenderSurfaceInterface::Type type )
+{
+}
+
+void DisplayConnectionCocoa::SetGraphicsInterface( GraphicsInterface& graphics )
+{
+  mGraphics = &graphics;
+}
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/display-connection-impl-mac.h b/dali/internal/window-system/macos/display-connection-impl-mac.h
new file mode 100644 (file)
index 0000000..9cb24bf
--- /dev/null
@@ -0,0 +1,99 @@
+#pragma once
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/window-system/common/display-connection-impl.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/internal/graphics/gles/egl-implementation.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+/**
+ * DisplayConnection implementation
+ */
+class DisplayConnectionCocoa : public Dali::Internal::Adaptor::DisplayConnection
+{
+public:
+
+  /**
+   * @brief Default constructor
+   */
+  DisplayConnectionCocoa();
+
+  /**
+   * @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::ConsumeEvents
+   */
+  void ConsumeEvents();
+
+  /**
+   * @copydoc Dali::DisplayConnection::InitializeEgl
+   */
+  bool InitializeEgl(EglInterface& egl);
+
+  /**
+  * @copydoc Dali::DisplayConnection::InitializeGraphics
+  */
+  bool InitializeGraphics();
+
+  /**
+  * @copydoc Dali::Internal::Adaptor::DisplayConnection::SetSurfaceType
+  */
+  void SetSurfaceType( Dali::RenderSurfaceInterface::Type type );
+
+  /**
+  * @copydoc Dali::Internal::Adaptor::DisplayConnection::SetGraphicsInterface
+  */
+  void SetGraphicsInterface( GraphicsInterface& graphics );
+
+public:
+
+  /**
+   * Destructor
+   */
+  virtual ~DisplayConnectionCocoa();
+
+private:
+
+  // Undefined
+  DisplayConnectionCocoa(const DisplayConnectionCocoa&) = delete;
+
+  // Undefined
+  DisplayConnectionCocoa& operator=(const DisplayConnectionCocoa& rhs) = delete;
+
+private:
+
+  GraphicsInterface *mGraphics; ///< The graphics interface
+};
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/render-surface-factory-mac.cpp b/dali/internal/window-system/macos/render-surface-factory-mac.cpp
new file mode 100644 (file)
index 0000000..1c76cf4
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 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 <dali/internal/window-system/macos/render-surface-factory-mac.h>
+
+// EXTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+
+// INTERNAL HEADERS
+#include <dali/integration-api/adaptor-framework/native-render-surface.h>
+#include <dali/internal/window-system/common/display-utils.h>
+#include <dali/internal/window-system/common/pixmap-render-surface.h>
+#include "window-render-surface-cocoa.h"
+
+namespace Dali::Internal::Adaptor
+{
+
+std::unique_ptr< WindowRenderSurface >
+RenderSurfaceFactoryCocoa::CreateWindowRenderSurface(
+  Dali::PositionSize positionSize,
+  Any surface,
+  bool isTransparent
+)
+{
+  return Utils::MakeUnique< WindowRenderSurfaceCocoa >( positionSize, surface, isTransparent );
+}
+
+std::unique_ptr< PixmapRenderSurface >
+RenderSurfaceFactoryCocoa::CreatePixmapRenderSurface(
+  Dali::PositionSize positionSize,
+  Any surface,
+  bool isTransparent
+)
+{
+  DALI_LOG_ERROR("Pixmap isn't been supported in Windows");
+  return nullptr;
+}
+
+std::unique_ptr< NativeRenderSurface >
+RenderSurfaceFactoryCocoa::CreateNativeRenderSurface(
+  SurfaceSize surfaceSize,
+  Any surface,
+  bool isTransparent
+)
+{
+  return std::unique_ptr< NativeRenderSurface >( nullptr );
+}
+
+// this should be created from somewhere
+std::unique_ptr< RenderSurfaceFactory > GetRenderSurfaceFactory()
+{
+  // returns Window factory
+  return Utils::MakeUnique< RenderSurfaceFactoryCocoa >();
+}
+
+} // namespace Dali::Adaptor::Internal
diff --git a/dali/internal/window-system/macos/render-surface-factory-mac.h b/dali/internal/window-system/macos/render-surface-factory-mac.h
new file mode 100644 (file)
index 0000000..52388ca
--- /dev/null
@@ -0,0 +1,47 @@
+#pragma once
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/window-system/common/render-surface-factory.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+class RenderSurfaceFactoryCocoa : public RenderSurfaceFactory
+{
+public:
+  std::unique_ptr< WindowRenderSurface > CreateWindowRenderSurface(
+    Dali::PositionSize positionSize,
+    Any surface,
+    bool isTransparent = false
+  ) override;
+
+  std::unique_ptr< PixmapRenderSurface > CreatePixmapRenderSurface(
+    Dali::PositionSize positionSize,
+    Any surface,
+    bool isTransparent = false
+  ) override;
+
+  std::unique_ptr< NativeRenderSurface > CreateNativeRenderSurface(
+    SurfaceSize surfaceSize,
+    Any surface,
+    bool isTransparent = false
+  ) override;
+};
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/window-base-mac.h b/dali/internal/window-system/macos/window-base-mac.h
new file mode 100644 (file)
index 0000000..547583d
--- /dev/null
@@ -0,0 +1,317 @@
+#pragma once
+
+/*
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/window-system/common/window-base.h>
+#include <memory>
+
+namespace Dali::Internal::Adaptor
+{
+
+/**
+ * WindowBaseCocoa class provides an WindowBase Win32 implementation.
+ */
+class WindowBaseCocoa : public WindowBase
+{
+public:
+
+  struct Impl;
+
+  /**
+   * @brief Constructor
+   */
+  WindowBaseCocoa( PositionSize positionSize, Any surface, bool isTransparent );
+
+  /**
+   * @brief Destructor
+   */
+  ~WindowBaseCocoa();
+
+public:
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetNativeWindow()
+   */
+  Any GetNativeWindow() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetNativeWindowId()
+   */
+  int GetNativeWindowId() override;
+
+  /**
+  * @copydoc Dali::Internal::Adaptor::WindowBase::CreateEglWindow()
+   */
+  EGLNativeWindowType CreateEglWindow( int width, int height ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::DestroyEglWindow()
+   */
+  void DestroyEglWindow() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetEglWindowRotation()
+   */
+  void SetEglWindowRotation( int angle ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetEglWindowBufferTransform()
+   */
+  void SetEglWindowBufferTransform( int angle ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetEglWindowTransform()
+   */
+  void SetEglWindowTransform( int angle ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::ResizeEglWindow()
+   */
+  void ResizeEglWindow( PositionSize positionSize ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::IsEglWindowRotationSupported()
+   */
+  bool IsEglWindowRotationSupported() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::Move()
+   */
+  void Move( PositionSize positionSize ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::Resize()
+   */
+  void Resize( PositionSize positionSize ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::MoveResize()
+   */
+  void MoveResize( PositionSize positionSize ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetClass()
+   */
+  void SetClass( const std::string& name, const std::string& className ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::Raise()
+   */
+  void Raise() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::Lower()
+   */
+  void Lower() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::Activate()
+   */
+  void Activate() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetAvailableAnlges()
+   */
+  void SetAvailableAnlges( const std::vector< int >& angles ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetPreferredAngle()
+   */
+  void SetPreferredAngle( int angle ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetAcceptFocus()
+   */
+  void SetAcceptFocus( bool accept ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::Show()
+   */
+  void Show() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::Hide()
+   */
+  void Hide() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetSupportedAuxiliaryHintCount()
+   */
+  unsigned int GetSupportedAuxiliaryHintCount() const override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetSupportedAuxiliaryHint()
+   */
+  std::string GetSupportedAuxiliaryHint( unsigned int index ) const override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::AddAuxiliaryHint()
+   */
+  unsigned int AddAuxiliaryHint( const std::string& hint, const std::string& value ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::RemoveAuxiliaryHint()
+   */
+  bool RemoveAuxiliaryHint( unsigned int id ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetAuxiliaryHintValue()
+   */
+  bool SetAuxiliaryHintValue( unsigned int id, const std::string& value ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetAuxiliaryHintValue()
+   */
+  std::string GetAuxiliaryHintValue( unsigned int id ) const override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetAuxiliaryHintId()
+   */
+  unsigned int GetAuxiliaryHintId( const std::string& hint ) const override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetInputRegion()
+   */
+  void SetInputRegion( const Rect< int >& inputRegion ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetType()
+   */
+  void SetType( Dali::WindowType type ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetNotificationLevel()
+   */
+  bool SetNotificationLevel( WindowNotificationLevel level ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetNotificationLevel()
+   */
+  WindowNotificationLevel GetNotificationLevel() const override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetOpaqueState()
+   */
+  void SetOpaqueState( bool opaque ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetScreenOffMode()
+   */
+  bool SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenOffMode()
+   */
+  WindowScreenOffMode GetScreenOffMode() const override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetBrightness()
+   */
+  bool SetBrightness( int brightness ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetBrightness()
+   */
+  int GetBrightness() const override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GrabKey()
+   */
+  bool GrabKey( Dali::KEY key, KeyGrab::KeyGrabMode grabMode ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::UngrabKey()
+   */
+  bool UngrabKey( Dali::KEY key ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GrabKeyList()
+   */
+  bool GrabKeyList(
+    const Dali::Vector< Dali::KEY >& key,
+    const Dali::Vector< KeyGrab::KeyGrabMode >& grabMode,
+    Dali::Vector< bool >& result
+  ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::UngrabKeyList()
+   */
+  bool UngrabKeyList(
+    const Dali::Vector< Dali::KEY >& key,
+    Dali::Vector< bool >& result
+  ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetDpi()
+   */
+  void GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+   */
+  int GetOrientation() const override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenRotationAngle()
+   */
+  int GetScreenRotationAngle() override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetWindowRotationAngle()
+   */
+  void SetWindowRotationAngle( int degree ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::WindowRotationCompleted()
+   */
+  void WindowRotationCompleted( int degree, int width, int height ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetTransparency()
+   */
+  void SetTransparency( bool transparent ) override;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::WindowBase::SetParent()
+   */
+  void SetParent( WindowBase* parentWinBase ) override;
+
+  /**
+   * @copydoc  Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence()
+   */
+  int CreateFrameRenderedSyncFence() override;
+
+  /**
+   * @copydoc  Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence()
+   */
+  int CreateFramePresentedSyncFence() override;
+
+private:
+
+  // Undefined
+  WindowBaseCocoa(const WindowBaseCocoa &) = delete;
+
+  // Undefined
+  WindowBaseCocoa& operator=(const WindowBaseCocoa& rhs) = delete;
+
+private:
+  std::unique_ptr<Impl> mImpl;
+};
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/window-base-mac.mm b/dali/internal/window-system/macos/window-base-mac.mm
new file mode 100644 (file)
index 0000000..b98f8a6
--- /dev/null
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "dali/public-api/adaptor-framework/window.h"
+#include "dali/public-api/events/wheel-event.h"
+#include <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+
+// CLASS HEADER
+#include <dali/internal/window-system/macos/window-base-mac.h>
+
+// EXTERNAL_HEADERS
+#include <dali/public-api/object/any.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL HEADERS
+#include <dali/internal/window-system/common/window-impl.h>
+#include <dali/internal/window-system/common/window-render-surface.h>
+#include <dali/internal/window-system/common/window-system.h>
+
+#include <cmath>
+
+using Dali::Internal::Adaptor::WindowBaseCocoa;
+
+// Angle is default selecting CGL as its backend and because
+// of that we are using NSOpenGLView. Ideally we should use
+// Metal as the backend. When this happends, we must change
+// the parent class to MTKView.
+@interface CocoaView : NSOpenGLView
+- (CocoaView *) initWithFrame:(NSRect) rect withImpl:(WindowBaseCocoa::Impl *) impl;
+- (BOOL) isFlipped;
+- (BOOL) wantsUpdateLayer;
+- (BOOL) acceptsFirstResponder;
+- (void) mouseDown:(NSEvent *) event;
+- (void) mouseUp:(NSEvent *) event;
+- (void) mouseDragged:(NSEvent *) event;
+- (void) keyDown:(NSEvent *) event;
+- (void) keyUp:(NSEvent *) event;
+- (void) drawRect:(NSRect) dirtyRect;
+- (void) prepareOpenGL;
+@end
+
+@interface WindowDelegate : NSObject <NSWindowDelegate>
+- (WindowDelegate *) init:(WindowBaseCocoa::Impl *) impl;
+- (void) windowDidBecomeKey:(NSNotification *) notification;
+- (void) windowDidResignKey:(NSNotification *) notification;
+- (void) windowWillClose:(NSNotification *) notification;
+@end
+
+namespace Dali::Internal::Adaptor
+{
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gWindowBaseLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_WINDOW_BASE" );
+#endif
+
+// Converts a y coordinate from top to bottom coordinate
+CGFloat BottomYCoordinate(CGFloat topYCoordinate, CGFloat windowHeight) noexcept
+{
+  const auto screen = [NSScreen.mainScreen frame];
+  return screen.size.height - windowHeight - topYCoordinate;
+}
+
+NSRect PositionSizeToRect(const PositionSize &positionSize, bool flipped = false) noexcept
+{
+  // positionSize assumes top-left coordinate system
+  // Cocoa assumes bottom-left coordinate system
+  // If NSView isFlipped method returns YES, then it uses top-left coordinate system
+  const auto windowHeight = static_cast<CGFloat>(positionSize.height);
+  const auto yGiven = static_cast<CGFloat>(positionSize.y);
+
+  CGFloat yWindow;
+  if (flipped)
+  {
+    yWindow = yGiven;
+  }
+  else
+  {
+    yWindow = BottomYCoordinate(yGiven, windowHeight);
+  }
+
+  return
+  {
+    .origin =
+    {
+      .x = static_cast<CGFloat>(positionSize.x),
+      .y = yWindow
+    },
+    .size =
+    {
+      .width = static_cast<CGFloat>(positionSize.width),
+      .height = windowHeight,
+    },
+  };
+}
+
+} // unnamed namespace
+
+struct WindowBaseCocoa::Impl final
+{
+  NSWindow *mWindow;
+  NSWindowController *mWinController;
+  WindowBaseCocoa *mThis;
+
+  Impl(const Impl &rhs) = delete;
+  Impl &operator<(const Impl &rhs) = delete;
+  Impl(const Impl &&rhs) = delete;
+  Impl &operator<(const Impl &&rhs) = delete;
+
+  Impl(
+    WindowBaseCocoa *pThis,
+    PositionSize positionSize,
+    Any surface,
+    bool isTransparent
+  );
+
+  ~Impl();
+
+  void OnFocus(bool focus)
+  {
+    mThis->mFocusChangedSignal.Emit(focus);
+  }
+
+  // Handle mouse events
+  void OnMouse(NSEvent *event, PointState::Type state);
+  void OnMouseWheel(NSEvent *event);
+  void OnKey(NSEvent *event, Integration::KeyEvent::State keyState);
+  void OnWindowDamaged(const NSRect &rect);
+
+  void OnRedraw(void)
+  {
+    mThis->mWindowRedrawRequestSignal.Emit();
+  }
+
+private:
+  uint32_t GetKeyModifiers(NSEvent *event) const noexcept;
+  std::string GetKeyName(NSEvent *event) const;
+};
+
+WindowBaseCocoa::Impl::Impl(
+  WindowBaseCocoa *pThis,
+  PositionSize positionSize,
+  Any surface,
+  bool isTransparent
+) : mThis(pThis)
+{
+  constexpr NSUInteger style =
+    NSWindowStyleMaskTitled
+    | NSWindowStyleMaskClosable
+    | NSWindowStyleMaskMiniaturizable
+    | NSWindowStyleMaskResizable;
+
+  mWindow = [[NSWindow alloc] initWithContentRect:PositionSizeToRect(positionSize)
+                                        styleMask:style
+                                          backing:NSBackingStoreBuffered
+                                            defer:NO];
+
+  mWindow.alphaValue = static_cast<CGFloat>(!isTransparent);
+  mWinController = [[NSWindowController alloc] initWithWindow:mWindow];
+
+  mWindow.delegate = [[WindowDelegate alloc] init:this];
+
+  NSView *view = [[CocoaView alloc] initWithFrame:PositionSizeToRect(positionSize, true)
+                                         withImpl:this];
+  NSPoint origin{0, 0};
+  [view setFrameOrigin:origin];
+
+  mWindow.contentView = view;
+
+  [mWindow makeKeyAndOrderFront:nil];
+}
+
+WindowBaseCocoa::Impl::~Impl()
+{
+  [mWinController close];
+  [NSApp stop:nil];
+}
+
+void WindowBaseCocoa::Impl::OnMouse(NSEvent *event, PointState::Type state)
+{
+  Integration::Point point;
+  point.SetDeviceId(event.deviceID);
+  point.SetState(state);
+  auto p = [event locationInWindow];
+  auto [x, y] = [mWindow.contentView convertPoint:p fromView:nil];
+  point.SetScreenPosition(Vector2(x, y));
+  point.SetRadius(std::sqrt(x*x + y*y));
+  point.SetPressure(event.pressure);
+
+  if (x == 0.0)
+  {
+    point.SetAngle(Degree(0.0));
+  }
+  else
+  {
+    point.SetAngle(Radian(std::atan(y/x)));
+  }
+
+  DALI_LOG_INFO(
+    gWindowBaseLogFilter,
+    Debug::Verbose,
+    "WindowBaseCocoa::Impl::OnMouse(%.1f, %.1f)\n",
+    x,
+    y
+  );
+
+  // timestamp is given in seconds, the signal expects it in milliseconds
+  mThis->mTouchEventSignal.Emit(point, event.timestamp * 1000);
+}
+
+void WindowBaseCocoa::Impl::OnMouseWheel(NSEvent *event)
+{
+  auto p = [event locationInWindow];
+  auto [x, y] = [mWindow.contentView convertPoint:p fromView:nil];
+
+  const auto modifiers = GetKeyModifiers(event);
+  const Vector2 vec(x, y);
+  const auto timestamp = event.timestamp * 1000;
+
+  if (event.scrollingDeltaY)
+  {
+    Integration::WheelEvent wheelEvent(
+      Integration::WheelEvent::MOUSE_WHEEL,
+      0,
+      modifiers,
+      vec,
+      event.scrollingDeltaY < 0 ? -1 : 1,
+      timestamp
+    );
+
+    mThis->mWheelEventSignal.Emit(wheelEvent);
+  }
+
+  if (event.scrollingDeltaX)
+  {
+    Integration::WheelEvent wheelEvent(
+      Integration::WheelEvent::MOUSE_WHEEL,
+      0,
+      modifiers,
+      vec,
+      event.scrollingDeltaX < 0 ? -1 : 1,
+      timestamp
+    );
+
+    mThis->mWheelEventSignal.Emit(wheelEvent);
+  }
+}
+
+void WindowBaseCocoa::Impl::OnKey(NSEvent *event, Integration::KeyEvent::State keyState)
+{
+  const std::string empty;
+
+  Integration::KeyEvent keyEvent(
+    GetKeyName(event),
+    empty,
+    [event.characters UTF8String],
+    event.keyCode,
+    GetKeyModifiers(event),
+    event.timestamp * 1000,
+    keyState,
+    empty,
+    empty,
+    Device::Class::NONE,
+    Device::Subclass::NONE
+  );
+
+  DALI_LOG_INFO(
+    gWindowBaseLogFilter,
+    Debug::Verbose,
+    "WindowBaseCocoa::Impl::OnKey(%s)\n",
+    [event.characters UTF8String]
+  );
+
+  mThis->mKeyEventSignal.Emit(keyEvent);
+}
+
+void WindowBaseCocoa::Impl::OnWindowDamaged(const NSRect &rect)
+{
+  const DamageArea area(
+    rect.origin.x,
+    rect.origin.y,
+    rect.size.width,
+    rect.size.height
+  );
+
+  mThis->mWindowDamagedSignal.Emit(area);
+}
+
+uint32_t WindowBaseCocoa::Impl::GetKeyModifiers(NSEvent *event) const noexcept
+{
+  uint32_t modifiers = 0;
+
+  if (event.modifierFlags & NSEventModifierFlagShift)
+  {
+    modifiers |= 1;
+  }
+
+  if (event.modifierFlags & NSEventModifierFlagControl)
+  {
+    modifiers |= 2;
+  }
+
+  if (event.modifierFlags & NSEventModifierFlagCommand)
+  {
+    modifiers |= 4;
+  }
+
+  return modifiers;
+}
+
+std::string WindowBaseCocoa::Impl::GetKeyName(NSEvent *event) const
+{
+  switch (event.keyCode)
+  {
+    case kVK_Control:     return "Control";
+    case kVK_Shift:       return "Shift";
+    case kVK_Delete:      return "Backspace";
+    case kVK_Command:     return "Command";
+    case kVK_Tab:         return "Tab";
+    case kVK_Return:      return "Return";
+    case kVK_Escape:      return "Escape";
+    case kVK_Space:       return "Space";
+    case kVK_LeftArrow:   return "Left";
+    case kVK_UpArrow:     return "Up";
+    case kVK_RightArrow:  return "Right";
+    case kVK_DownArrow:   return "Down";
+    case kVK_ANSI_0:      return "0";
+    case kVK_ANSI_1:      return "1";
+    case kVK_ANSI_2:      return "2";
+    case kVK_ANSI_3:      return "3";
+    case kVK_ANSI_4:      return "4";
+    case kVK_ANSI_5:      return "5";
+    case kVK_ANSI_6:      return "6";
+    case kVK_ANSI_7:      return "7";
+    case kVK_ANSI_8:      return "8";
+    case kVK_ANSI_9:      return "9";
+    default:              return [event.characters UTF8String];
+  }
+
+  return "";
+}
+
+WindowBaseCocoa::WindowBaseCocoa(PositionSize positionSize, Any surface, bool isTransparent)
+  : mImpl(std::make_unique<Impl>(this, positionSize, surface, isTransparent))
+{
+}
+
+WindowBaseCocoa::~WindowBaseCocoa()
+{
+}
+
+Any WindowBaseCocoa::GetNativeWindow()
+{
+  return mImpl->mWindow;
+}
+
+int WindowBaseCocoa::GetNativeWindowId()
+{
+  return mImpl->mWindow.windowNumber;
+}
+
+EGLNativeWindowType WindowBaseCocoa::CreateEglWindow(int width, int height)
+{
+  // XXX: this method is called from a secondary thread, but
+  // we can only resize the window from the main thread
+  //PositionSize size(0, 0, width, height);
+  //Resize(size);
+  return mImpl->mWindow.contentView.layer;
+}
+
+void WindowBaseCocoa::DestroyEglWindow()
+{
+}
+
+void WindowBaseCocoa::SetEglWindowRotation( int angle )
+{
+}
+
+void WindowBaseCocoa::SetEglWindowBufferTransform( int angle )
+{
+}
+
+void WindowBaseCocoa::SetEglWindowTransform( int angle )
+{
+}
+
+void WindowBaseCocoa::ResizeEglWindow( PositionSize positionSize )
+{
+  Resize(positionSize);
+}
+
+bool WindowBaseCocoa::IsEglWindowRotationSupported()
+{
+  return false;
+}
+
+void WindowBaseCocoa::Move( PositionSize positionSize )
+{
+  const NSPoint p = {
+    .x = static_cast<CGFloat>(positionSize.x),
+    .y = static_cast<CGFloat>(positionSize.y),
+  };
+
+  [mImpl->mWindow setFrameTopLeftPoint:p];
+}
+
+void WindowBaseCocoa::Resize( PositionSize positionSize )
+{
+  auto r = mImpl->mWindow.frame;
+  r.size.width = static_cast<CGFloat>(positionSize.width);
+  r.size.height = static_cast<CGFloat>(positionSize.height);
+  [mImpl->mWindow setFrame:r display:YES];
+
+  NSSize size =
+  {
+    .width = r.size.width,
+    .height = r.size.height,
+  };
+
+  [mImpl->mWindow.contentView setFrameSize:size];
+
+}
+
+void WindowBaseCocoa::MoveResize( PositionSize positionSize )
+{
+  [mImpl->mWindow setFrame: PositionSizeToRect(positionSize) display:YES];
+
+  NSSize size =
+  {
+    .width = static_cast<CGFloat>(positionSize.width),
+    .height = static_cast<CGFloat>(positionSize.height),
+  };
+
+  [mImpl->mWindow.contentView setFrameSize:size];
+}
+
+void WindowBaseCocoa::SetClass( const std::string& name, const std::string& className )
+{
+}
+
+void WindowBaseCocoa::Raise()
+{
+  [mImpl->mWindow orderFront:nil];
+}
+
+void WindowBaseCocoa::Lower()
+{
+  [mImpl->mWindow orderBack:nil];
+}
+
+void WindowBaseCocoa::Activate()
+{
+  [mImpl->mWinController showWindow:nil];
+}
+
+void WindowBaseCocoa::SetAvailableAnlges( const std::vector< int >& angles )
+{
+}
+
+void WindowBaseCocoa::SetPreferredAngle( int angle )
+{
+}
+
+void WindowBaseCocoa::SetAcceptFocus( bool accept )
+{
+}
+
+void WindowBaseCocoa::Show()
+{
+  [mImpl->mWinController showWindow:nil];
+}
+
+void WindowBaseCocoa::Hide()
+{
+  [mImpl->mWindow orderOut:nil];
+}
+
+unsigned int WindowBaseCocoa::GetSupportedAuxiliaryHintCount() const
+{
+  return 0;
+}
+
+std::string WindowBaseCocoa::GetSupportedAuxiliaryHint( unsigned int index ) const
+{
+  return std::string();
+}
+
+unsigned int WindowBaseCocoa::AddAuxiliaryHint( const std::string& hint, const std::string& value )
+{
+  return 0;
+}
+
+bool WindowBaseCocoa::RemoveAuxiliaryHint( unsigned int id )
+{
+  return false;
+}
+
+bool WindowBaseCocoa::SetAuxiliaryHintValue( unsigned int id, const std::string& value )
+{
+  return false;
+}
+
+std::string WindowBaseCocoa::GetAuxiliaryHintValue( unsigned int id ) const
+{
+  return std::string();
+}
+
+unsigned int WindowBaseCocoa::GetAuxiliaryHintId( const std::string& hint ) const
+{
+  return 0;
+}
+
+void WindowBaseCocoa::SetInputRegion( const Rect< int >& inputRegion )
+{
+}
+
+void WindowBaseCocoa::SetType( Dali::WindowType type )
+{
+}
+
+bool WindowBaseCocoa::SetNotificationLevel( WindowNotificationLevel level )
+{
+  return false;
+}
+
+WindowNotificationLevel WindowBaseCocoa::GetNotificationLevel() const
+{
+  return WindowNotificationLevel::NONE;
+}
+
+void WindowBaseCocoa::SetOpaqueState( bool opaque )
+{
+}
+
+bool WindowBaseCocoa::SetScreenOffMode(WindowScreenOffMode screenOffMode)
+{
+  return false;
+}
+
+WindowScreenOffMode WindowBaseCocoa::GetScreenOffMode() const
+{
+  return WindowScreenOffMode::TIMEOUT;
+}
+
+bool WindowBaseCocoa::SetBrightness( int brightness )
+{
+  return false;
+}
+
+int WindowBaseCocoa::GetBrightness() const
+{
+  return 0;
+}
+
+bool WindowBaseCocoa::GrabKey( Dali::KEY key, KeyGrab::KeyGrabMode grabMode )
+{
+  return false;
+}
+
+bool WindowBaseCocoa::UngrabKey( Dali::KEY key )
+{
+  return false;
+}
+
+bool WindowBaseCocoa::GrabKeyList(
+  const Dali::Vector< Dali::KEY >& key,
+  const Dali::Vector< KeyGrab::KeyGrabMode >& grabMode,
+  Dali::Vector< bool >& result
+)
+{
+  return false;
+}
+
+bool WindowBaseCocoa::UngrabKeyList(
+  const Dali::Vector< Dali::KEY >& key,
+  Dali::Vector< bool >& result
+)
+{
+  return false;
+}
+
+void WindowBaseCocoa::GetDpi(
+  unsigned int& dpiHorizontal,
+  unsigned int& dpiVertical
+)
+{
+  auto *screen = [NSScreen mainScreen];
+  NSSize res = [screen.deviceDescription[NSDeviceResolution] sizeValue];
+  dpiHorizontal = res.width;
+  dpiVertical = res.height;
+}
+
+int WindowBaseCocoa::GetOrientation() const
+{
+  return 0;
+}
+
+int WindowBaseCocoa::GetScreenRotationAngle()
+{
+  return 0;
+}
+
+void WindowBaseCocoa::SetWindowRotationAngle( int degree )
+{
+}
+
+void WindowBaseCocoa::WindowRotationCompleted( int degree, int width, int height )
+{
+}
+
+void WindowBaseCocoa::SetTransparency( bool transparent )
+{
+  mImpl->mWindow.alphaValue = static_cast<CGFloat>(!transparent);
+}
+
+void WindowBaseCocoa::SetParent( WindowBase* parentWinBase )
+{
+  auto &parent = dynamic_cast<WindowBaseCocoa&>(*parentWinBase);
+  [mImpl->mWindow setParentWindow:parent.mImpl->mWindow];
+}
+
+int WindowBaseCocoa::CreateFrameRenderedSyncFence()
+{
+  return -1;
+}
+
+int WindowBaseCocoa::CreateFramePresentedSyncFence()
+{
+  return -1;
+}
+
+} // namespace Dali::Internal::Adaptor
+
+@implementation CocoaView
+{
+  WindowBaseCocoa::Impl *mImpl;
+}
+
+- (CocoaView *) initWithFrame:(NSRect) rect withImpl:(WindowBaseCocoa::Impl *) impl
+{
+  self = [super initWithFrame:rect];
+  if (self)
+  {
+    mImpl = impl;
+    self.wantsLayer = YES;
+    self.wantsBestResolutionOpenGLSurface = NO;
+  }
+
+  return self;
+}
+
+- (BOOL) isFlipped
+{
+  return YES;
+}
+
+- (BOOL) wantsUpdateLayer
+{
+  return YES;
+}
+
+- (BOOL) acceptsFirstResponder
+{
+  return YES;
+}
+
+- (void) mouseDown:(NSEvent *) event
+{
+  mImpl->OnMouse(event, Dali::PointState::DOWN);
+}
+
+- (void) mouseUp:(NSEvent *) event
+{
+  mImpl->OnMouse(event, Dali::PointState::UP);
+}
+
+- (void) mouseDragged:(NSEvent *) event
+{
+  mImpl->OnMouse(event, Dali::PointState::MOTION);
+}
+
+- (void) keyDown:(NSEvent *) event
+{
+  mImpl->OnKey(event, Dali::Integration::KeyEvent::DOWN);
+}
+
+- (void) keyUp:(NSEvent *) event
+{
+  mImpl->OnKey(event, Dali::Integration::KeyEvent::UP);
+}
+
+- (void) drawRect:(NSRect) dirtyRect
+{
+  DALI_LOG_INFO(
+    Dali::Internal::Adaptor::gWindowBaseLogFilter,
+    Debug::Verbose,
+    "-[CocoaView drawRect:(%.1f, %.1f, %.1f, %.1f)]\n",
+    dirtyRect.origin.x,
+    dirtyRect.origin.y,
+    dirtyRect.size.width,
+    dirtyRect.size.height
+  );
+
+  mImpl->OnWindowDamaged(dirtyRect);
+}
+
+- (void) prepareOpenGL
+{
+  auto ctx = CGLGetCurrentContext();
+  DALI_ASSERT_ALWAYS(ctx);
+
+  // Enable multithreading
+  if (auto err = CGLEnable(ctx, kCGLCEMPEngine); err != kCGLNoError)
+  {
+    DALI_LOG_ERROR("%s - %s", __PRETTY_FUNCTION__, CGLErrorString(err));
+  }
+}
+@end
+
+@implementation WindowDelegate
+{
+  WindowBaseCocoa::Impl *mImpl;
+}
+
+- (WindowDelegate *) init:(Dali::Internal::Adaptor::WindowBaseCocoa::Impl *) impl
+{
+  self = [super init];
+  if (self)
+  {
+    mImpl = impl;
+  }
+  return self;
+}
+
+- (void) windowDidBecomeKey:(NSNotification *) notification
+{
+  mImpl->OnFocus(true);
+}
+
+- (void) windowDidResignKey:(NSNotification *) notification
+{
+  mImpl->OnFocus(false);
+}
+
+- (void) windowWillClose:(NSNotification *) notification
+{
+  [NSApp stop:nil];
+}
+@end
+
diff --git a/dali/internal/window-system/macos/window-factory-mac.cpp b/dali/internal/window-system/macos/window-factory-mac.cpp
new file mode 100644 (file)
index 0000000..bb1ad51
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020 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 <dali/internal/window-system/macos/window-factory-mac.h>
+
+// INTERNAL HEADERS
+#include <dali/internal/window-system/macos/window-base-mac.h>
+#include <dali/internal/window-system/common/display-utils.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+std::unique_ptr<WindowBase> WindowFactoryCocoa::CreateWindowBase(
+  Dali::PositionSize positionSize,
+  Any surface,
+  bool isTransparent
+)
+{
+  return Utils::MakeUnique< WindowBaseCocoa >( positionSize, surface, isTransparent );
+}
+
+// this should be created from Window impl
+std::unique_ptr< WindowFactory > GetWindowFactory()
+{
+  // returns Window factory
+  return Utils::MakeUnique< WindowFactoryCocoa >();
+}
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/window-factory-mac.h b/dali/internal/window-system/macos/window-factory-mac.h
new file mode 100644 (file)
index 0000000..19c33ce
--- /dev/null
@@ -0,0 +1,35 @@
+#pragma once
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/window-system/common/window-factory.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+class WindowFactoryCocoa : public WindowFactory
+{
+public:
+  std::unique_ptr<WindowBase> CreateWindowBase(
+    Dali::PositionSize positionSize,
+    Any surface,
+    bool isTransparent
+  ) override;
+};
+
+} // namespace Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/window-render-surface-cocoa.cpp b/dali/internal/window-system/macos/window-render-surface-cocoa.cpp
new file mode 100644 (file)
index 0000000..90d0d0d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020 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 "window-render-surface-cocoa.h"
+
+namespace Dali::Internal::Adaptor
+{
+WindowRenderSurfaceCocoa::WindowRenderSurfaceCocoa(Dali::PositionSize positionSize, Any surface, bool isTransparent)
+  : WindowRenderSurface(positionSize, surface, isTransparent)
+  , mReady(false)
+{
+}
+
+void WindowRenderSurfaceCocoa::StartRender()
+{
+  std::unique_lock<std::mutex> lock(mCondMutex);
+  WindowRenderSurface::StartRender();
+  while (!mReady)
+  {
+    mRenderWait.wait(lock);
+  }
+}
+
+void WindowRenderSurfaceCocoa::CreateSurface()
+{
+  std::lock_guard<std::mutex> lock(mCondMutex);
+  WindowRenderSurface::CreateSurface();
+  mReady = true;
+  mRenderWait.notify_all();
+}
+} // Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/window-render-surface-cocoa.h b/dali/internal/window-system/macos/window-render-surface-cocoa.h
new file mode 100644 (file)
index 0000000..7e573a4
--- /dev/null
@@ -0,0 +1,57 @@
+#pragma once
+
+/*
+ * Copyright (c) 2020 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 <mutex>
+#include <condition_variable>
+
+// INTERNAL INCLUDES
+#include <dali/internal/window-system/common/window-render-surface.h>
+
+namespace Dali::Internal::Adaptor
+{
+/**
+ * We must create the EGL Window before we enter the run loop.
+ * This specialization ensures this condition is respected.
+ */
+class WindowRenderSurfaceCocoa : public WindowRenderSurface
+{
+public:
+
+  /**
+   * @copydoc Dali::WindowRenderSurface()
+   */
+  WindowRenderSurfaceCocoa(Dali::PositionSize positionSize, Any surface, bool isTransparent = true);
+
+  /**
+   * @copydoc Dali::RenderSurfaceInterface::StartRender()
+   */
+  void StartRender() override;
+
+  /**
+   * @copydoc Dali::RenderSurfaceInterface::CreateSurface()
+   */
+  void CreateSurface() override;
+
+private:
+  std::mutex mCondMutex;
+  std::condition_variable mRenderWait;
+  bool mReady;
+};
+} // Dali::Internal::Adaptor
diff --git a/dali/internal/window-system/macos/window-system-mac.mm b/dali/internal/window-system/macos/window-system-mac.mm
new file mode 100644 (file)
index 0000000..9d2ee83
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 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.
+ *
+ */
+
+#import <Cocoa/Cocoa.h>
+
+// INTERNAL HEADERS
+#include <dali/internal/window-system/common/window-system.h>
+
+namespace Dali::Internal::Adaptor::WindowSystem
+{
+
+void Initialize()
+{
+}
+
+void GetScreenSize( int& width, int& height )
+{
+  NSRect r = [[NSScreen mainScreen] frame];
+  width = static_cast<int>(r.size.width);
+  height = static_cast<int>(r.size.height);
+}
+
+bool SetKeyboardRepeatInfo( float rate, float delay )
+{
+  return false;
+}
+
+bool GetKeyboardRepeatInfo( float& rate, float& delay )
+{
+  return false;
+}
+
+} // namespace Dali::Internal::Adaptor::WindowSystem
+
index c56d31e..4a2a60b 100755 (executable)
@@ -261,13 +261,24 @@ void CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT_PTR nTimerid, DWORD dwTime)
 
 intptr_t SetTimer(int interval, timerCallback callback, void *data)
 {
+  HWND hwnd = GetActiveWindow();
+  if (!hwnd)
+  {
+    hwnd = FindWindow(DALI_WINDOW_CLASS_NAME.c_str(), nullptr);
+  }
+
+  if (!hwnd)
+  {
+    return -1;
+  }
+
   TTimerCallbackInfo *callbackInfo = new TTimerCallbackInfo;
   callbackInfo->data = data;
   callbackInfo->callback = callback;
-  callbackInfo->hWnd = ::GetActiveWindow();
+  callbackInfo->hWnd = hwnd;
 
   INT_PTR timerID = (INT_PTR)callbackInfo;
-  ::SetTimer( callbackInfo->hWnd, timerID, interval, TimerProc );
+  ::SetTimer( hwnd, timerID, interval, TimerProc );
 
   return timerID;
 }
index 3b744ff..8ff304e 100644 (file)
@@ -27,7 +27,7 @@ namespace Dali
 {
 const unsigned int ADAPTOR_MAJOR_VERSION = 2;
 const unsigned int ADAPTOR_MINOR_VERSION = 0;
-const unsigned int ADAPTOR_MICRO_VERSION = 7;
+const unsigned int ADAPTOR_MICRO_VERSION = 8;
 const char* const  ADAPTOR_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index fecc75d..f259109 100644 (file)
@@ -17,7 +17,7 @@
 
 Name:       dali2-adaptor
 Summary:    The DALi Tizen Adaptor
-Version:    2.0.7
+Version:    2.0.8
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT
index e4623f2..918eeac 100644 (file)
@@ -38,3 +38,7 @@ SET( static_libraries_nanosvg_src_files
   ${adaptor_thirdparty_dir}/nanosvg/nanosvgrast.cc
 )
 
+SET( adaptor_macos_platform_src_files
+    ${adaptor_thirdparty_dir}/macos-platform/environment.cpp
+    ${adaptor_thirdparty_dir}/macos-platform/thread.cpp
+)
diff --git a/third-party/macos-platform/environment.cpp b/third-party/macos-platform/environment.cpp
new file mode 100644 (file)
index 0000000..ddecce9
--- /dev/null
@@ -0,0 +1,15 @@
+#include <cstdlib>
+#include <string>
+
+const char* app_get_data_path()
+{
+  static std::string envValue;
+
+  if( envValue.empty() )
+  {
+    envValue = std::getenv( "DemoData" );
+    envValue += "/";
+  }
+
+  return envValue.c_str();
+}
diff --git a/third-party/macos-platform/extern-definitions.h b/third-party/macos-platform/extern-definitions.h
new file mode 100644 (file)
index 0000000..c6af7e2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#pragma once
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <memory>
+#include <type_traits>
+
+const char* app_get_data_path();
+
+// Specialiation of std::unique_ptr for Foundation Objects
+template<typename T>
+using CFRef = std::unique_ptr<
+  std::remove_pointer_t<T>,
+  std::add_pointer_t<decltype(CFRelease)>
+>;
+
+template<typename T>
+inline CFRef<T> MakeRef(T p)
+{
+  return CFRef<T>(p, CFRelease);
+}
diff --git a/third-party/macos-platform/sys/prctl.h b/third-party/macos-platform/sys/prctl.h
new file mode 100644 (file)
index 0000000..5824488
--- /dev/null
@@ -0,0 +1,13 @@
+#pragma once
+
+#define PR_SET_NAME 0
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int prctl(int type, const char *str);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/third-party/macos-platform/thread.cpp b/third-party/macos-platform/thread.cpp
new file mode 100644 (file)
index 0000000..4de88b6
--- /dev/null
@@ -0,0 +1,11 @@
+#include <sys/prctl.h>
+#include <pthread.h>
+
+extern "C" int prctl( int type, const char *str )
+{
+  if (PR_SET_NAME == type)
+  {
+    pthread_setname_np(str);
+  }
+  return 0;
+}