Support for the macOS platform 66/244066/17
authorWander Lairson Costa <wander.lairson@gmail.com>
Thu, 13 Aug 2020 20:59:40 +0000 (17:59 -0300)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 5 Jan 2021 18:26:24 +0000 (18:26 +0000)
This commit provides basic support for the macOS platform.

The macOS specific bits are in part implemented in Objectve-C++ under
the Cocoa Framework.

One note is that we installed libANGLE through vcpkg, and it is using
CGL as the default backend. We should fix this in the future in favor of
the Metal Framework.

We added a new build profile called macos, and the cmake options
"-DENABLE_PROFILE=MACOS -DPROFILE_LCASE=macos" must be passed in the
command line to build it successfully.

cairo and fontconfig packages must be installed through brew, the
version provided by vcpkg doesn't work on macOS (actually, only
fontconfig is necessary, but if you install cairo through vcpkg, it will
pull fontconfig as well).

Change-Id: Ibcf4f854721a48e3ae4e5bd710182d0dae893e05

49 files changed:
.gitignore
build/tizen/CMakeLists.txt
build/tizen/deps-check.cmake
build/tizen/profiles/macos-profile.cmake [new file with mode: 0644]
dali/internal/accessibility/file.list
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/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-system-mac.mm [new file with mode: 0644]
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 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..51aa89b
--- /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( 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::libANGLE
+  unofficial::angle::libGLESv2
+  unofficial::angle::angle_common
+  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 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 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 d3a73ac..8a8bccd 100644 (file)
@@ -66,3 +66,13 @@ 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-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..caa386e
--- /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 <dali/internal/window-system/common/window-render-surface.h>
+
+namespace Dali::Internal::Adaptor
+{
+
+std::unique_ptr< WindowRenderSurface >
+RenderSurfaceFactoryCocoa::CreateWindowRenderSurface(
+  Dali::PositionSize positionSize,
+  Any surface,
+  bool isTransparent
+)
+{
+  return Utils::MakeUnique< WindowRenderSurface >( 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-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 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;
+}