INCLUDE( deps-check.cmake )
ENDIF()
-IF( UBUNTU_PROFILE OR ANDROID_PROFILE OR WIN32 OR APPLE OR LIBUV_X11_PROFILE )
+IF( UBUNTU_PROFILE OR ANDROID_PROFILE OR WIN32 OR APPLE OR LIBUV_X11_PROFILE OR GLIB_X11_PROFILE)
SET( ENABLE_VCONF OFF )
ELSE()
SET( ENABLE_VCONF ON )
ENDIF()
-IF( NOT DALI_ELDBUS_AVAILABLE OR LIBUV_X11_PROFILE )
+IF( NOT DALI_ELDBUS_AVAILABLE OR LIBUV_X11_PROFILE OR GLIB_X11_PROFILE)
SET( ENABLE_ATSPI OFF )
ENDIF()
ENDIF()
# Test for profile and exit if something wrong
-SET( VALID_PROFILES COMMON MOBILE WEARABLE TV IVI UBUNTU ANDROID WINDOWS MACOS LIBUV_X11)
+SET( VALID_PROFILES COMMON MOBILE WEARABLE TV IVI UBUNTU ANDROID WINDOWS MACOS LIBUV_X11 GLIB_X11)
LIST( FIND VALID_PROFILES ${enable_profile} RESULT )
IF( RESULT EQUAL -1 )
MESSAGE( FATAL_ERROR "Invalid profile!" )
# Defines profile specific variable
SET( ${enable_profile}_PROFILE 1 )
-IF( LIBUV_X11_PROFILE )
+IF( LIBUV_X11_PROFILE OR GLIB_X11_PROFILE )
SET( X11_REQUIRED 1 )
ENDIF()
CHECK_MODULE_AND_SET( TTS tts [] )
CHECK_MODULE_AND_SET( VCONF vconf [] )
CHECK_MODULE_AND_SET( LIBUV libuv [] )
+CHECK_MODULE_AND_SET( GLIB glib-2.0 [] )
CHECK_MODULE_AND_SET( X11 x11 [] )
CHECK_MODULE_AND_SET( XDAMAGE xdamage [] )
CHECK_MODULE_AND_SET( XFIXES xfixes [] )
ENDIF()
# Android includes pthread with android lib
-if( NOT ANDROID_PROFILE )
+IF( NOT ANDROID_PROFILE )
SET( DALI_LDFLAGS ${DALI_LDFLAGS}
-lpthread
)
)
ENDIF()
+
IF(X11_REQUIRED)
SET( DALI_CFLAGS ${DALI_CFLAGS}
- ${LIBUV_CFLAGS}
${X11_CFLAGS}
${XDAMAGE_CFLAGS}
${XFIXES_CFLAGS}
)
SET( DALI_LDFLAGS ${DALI_LDFLAGS}
- ${LIBUV_LDFLAGS}
${X11_LDFLAGS}
${XDAMAGE_LDFLAGS}
${XFIXES_LDFLAGS}
)
ENDIF()
+IF(LIBUV_X11_PROFILE)
+ SET(DALI_CFLAGS ${DALI_CFLAGS} ${LIBUV_CFLAGS})
+ SET(DALI_LDFLAGS ${DALI_LDFLAGS} ${LIBUV_LDFLAGS})
+ELSEIF(GLIB_X11_PROFILE)
+ SET(DALI_CFLAGS ${DALI_CFLAGS} ${GLIB_CFLAGS})
+ SET(DALI_LDFLAGS ${DALI_LDFLAGS} ${GLIB_LDFLAGS})
+ENDIF()
+
+
# COMMON PROFILE
IF( COMMON_PROFILE )
SET( DALI_CFLAGS ${DALI_CFLAGS} ${HAPTIC_CFLAGS} )
# UBUNTU PROFILE
IF( UBUNTU_PROFILE )
SET( DALI_CFLAGS ${DALI_CFLAGS} -fPIC )
- SET( DALI_LDFLAGS ${DALI_LDFLAGS} -ljpeg )
+ SET( DALI_LDFLAGS ${DALI_LDFLAGS} -ljpeg)
+ENDIF()
+
+# Dali depends on shm_open, but librt is usually included from framework (ecore, libuv etc)
+IF( GLIB_X11_PROFILE)
+ SET( DALI_LDFLAGS ${DALI_LDFLAGS} -lrt)
ENDIF()
-IF( NOT COMMON_PROFILE )
+IF( NOT COMMON_PROFILE AND NOT X11_REQUIRED)
ADD_DEFINITIONS( -DWAYLAND_EXTENSIONS_SUPPORTED )
ENDIF()
--- /dev/null
+# PROFILE: GLIB_X11
+
+# Set the sources
+SET( SOURCES
+ ${adaptor_accessibility_common_src_files}
+ ${adaptor_accessibility_glib_x11_src_files}
+ ${adaptor_adaptor_common_src_files}
+ ${adaptor_adaptor_glib_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_ubuntu_src_files}
+ ${adaptor_camera_common_src_files}
+ ${adaptor_canvas_renderer_generic_src_files}
+ ${adaptor_clipboard_common_src_files}
+ ${adaptor_clipboard_glib_x11_src_files}
+ ${adaptor_drag_and_drop_generic_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_x11_src_files}
+ ${adaptor_haptics_common_src_files}
+ ${adaptor_imaging_common_src_files}
+ ${adaptor_imaging_x11_src_files}
+ ${adaptor_input_common_src_files}
+ ${adaptor_input_generic_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_styling_common_src_files}
+ ${adaptor_system_common_src_files}
+ ${adaptor_system_glib_src_files}
+ ${adaptor_resampler_src_files}
+ ${adaptor_text_common_src_files}
+ ${adaptor_thread_common_src_files}
+ ${adaptor_trace_common_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_window_system_x11_src_files}
+ ${devel_api_text_abstraction_src_files}
+ ${static_libraries_libunibreak_src_files}
+)
+
+IF( ENABLE_VECTOR_BASED_TEXT_RENDERING )
+ SET( SOURCES ${SOURCES}
+ ${static_libraries_glyphy_src_files}
+ )
+ENDIF()
+
+IF( NOT thorvg_support)
+ SET( SOURCES ${SOURCES}
+ ${static_libraries_nanosvg_src_files}
+ )
+ENDIF()
+
+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()
+
+# Set the header directories
+SET( PROFILE_INCLUDE_DIRECTORIES
+ ${EXIF_INCLUDE_DIRS}
+ ${FREETYPE_INCLUDE_DIRS}
+ ${FREETYPE_BITMAP_SUPPORT}
+ ${FONTCONFIG_INCLUDE_DIRS}
+ ${PNG_INCLUDE_DIRS}
+ ${LIBEXIF_INCLUDE_DIRS}
+ ${LIBDRM_INCLUDE_DIRS}
+ ${LIBCURL_INCLUDE_DIRS}
+ ${LIBCRYPTO_INCLUDE_DIRS}
+ ${HARFBUZZ_INCLUDE_DIRS}
+ ${FRIBIDI_INCLUDE_DIRS}
+ ${CAIRO_INCLUDE_DIRS}
+ ${CAPI_APPFW_APPLICATION_INCLUDE_DIRS}
+ ${X11_INCLUDE_DIRS}
+ ${DALICORE_INCLUDE_DIRS}
+ )
+
+# Set compile options
+ADD_COMPILE_OPTIONS(
+ ${DALI_ADAPTOR_CFLAGS}
+ ${DALICORE_CFLAGS}
+ ${OPENGLES20_CFLAGS}
+ ${FREETYPE_CFLAGS}
+ ${FONTCONFIG_CFLAGS}
+ ${CAIRO_CFLAGS}
+ ${PNG_CFLAGS}
+ ${DLOG_CFLAGS}
+ ${VCONF_CFLAGS}
+ ${EXIF_CFLAGS}
+ ${MMFSOUND_CFLAGS}
+ ${TTS_CFLAGS}
+ ${CAPI_SYSTEM_SENSOR_CFLAGS}
+ ${LIBDRM_CFLAGS}
+ ${LIBEXIF_CFLAGS}
+ ${LIBCURL_CFLAGS}
+ ${LIBCRYPTO_CFLAGS}
+ ${UTILX_CFLAGS}
+)
+
+# Set the linker flags
+SET(REQUIRED_LIBS
+ ${EXIF_LDFLAGS}
+ ${FREETYPE_LDFLAGS}
+ ${FREETYPE_BITMAP_SUPPORT}
+ ${FONTCONFIG_LDFLAGS}
+ ${PNG_LDFLAGS}
+ ${LIBEXIF_LDFLAGS}
+ ${LIBDRM_LDFLAGS}
+ ${LIBCURL_LDFLAGS}
+ ${LIBCRYPTO_LDFLAGS}
+ ${HARFBUZZ_LDFLAGS}
+ ${FRIBIDI_LDFLAGS}
+ ${CAIRO_LDFLAGS}
+ ${CAPI_APPFW_APPLICATION_LDFLAGS}
+ ${X11_LDFLAGS}
+ ${DALICORE_LDFLAGS}
+ ${OPENGLES20_LDFLAGS}
+ ${EGL_LDFLAGS}
+ -lgif
+ -lpthread
+ -lturbojpeg
+ -ljpeg
+ -lhyphen
+)
+
+
+FIND_LIBRARY( HYPHEN_LIBRARY NAMES hyphen )
+IF (${HYPHEN_LIBRARY} MATCHES "HYPHEN_LIBRARY-NOTFOUND")
+ UNSET (HYPHEN_LIBRARY_AVAILABLE)
+ELSE()
+ SET (HYPHEN_LIBRARY_AVAILABLE "HYPHEN_LIBRARY_AVAILABLE")
+ ADD_DEFINITIONS(-DHYPHEN_LIBRARY_AVAILABLE="${HYPHEN_LIBRARY_AVAILABLE}")
+
+ #The path of hyphen library dictionary
+ IF (NOT "${HYPHEN_DIC}")
+ FIND_PATH(HYPHEN_DIC hyph_en_US.dic HINTS "/usr/local/share/hyphen" "/usr/share/hyphen" )
+ IF ( NOT HYPHEN_DIC MATCHES "HYPHEN_DIC-NOTFOUND")
+ ADD_DEFINITIONS(-DHYPHEN_DIC="${HYPHEN_DIC}")
+ ENDIF()
+ ENDIF()
+ MESSAGE (HYPHEN_DIC: "${HYPHEN_DIC}")
+
+ENDIF()
${adaptor_accessibility_dir}/generic/tts-player-impl-generic.cpp
)
+# module: accessibility, backend: glib_x11 profile
+SET( adaptor_accessibility_glib_x11_src_files
+ ${adaptor_accessibility_dir}/generic/tts-player-factory-generic.cpp
+ ${adaptor_accessibility_dir}/generic/tts-player-impl-generic.cpp
+)
+
# module: accessibility, backend: windows
SET( adaptor_accessibility_windows_src_files
)
mPerformanceInterface->AddMarker(PerformanceInterface::PROCESS_EVENTS_START);
}
-#if !defined(DALI_PROFILE_UBUNTU) && !defined(DALI_PROFILE_LIBUV_X11)
+#if !defined(DALI_PROFILE_UBUNTU) && !defined(DALI_PROFILE_LIBUV_X11) && !defined(DALI_PROFILE_GLIB_X11)
DALI_LOG_RELEASE_INFO("Start ProcessEvents\n");
#endif
mCore->ProcessEvents();
-#if !defined(DALI_PROFILE_UBUNTU) && !defined(DALI_PROFILE_LIBUV_X11)
+#if !defined(DALI_PROFILE_UBUNTU) && !defined(DALI_PROFILE_LIBUV_X11) && !defined(DALI_PROFILE_GLIB_X11)
DALI_LOG_RELEASE_INFO("End ProcessEvents\n");
#endif
${adaptor_adaptor_dir}/libuv/framework-libuv.cpp
)
+# module: adaptor, backend: glib-x11
+SET( adaptor_adaptor_glib_src_files
+ ${adaptor_adaptor_dir}/generic/adaptor-impl-generic.cpp
+ ${adaptor_adaptor_dir}/glib/framework-glib.cpp
+)
+
# module: adaptor, backend: tizen-wearable
SET( adaptor_adaptor_tizen_wearable_src_files
${adaptor_adaptor_dir}/tizen-wayland/tizen-wearable/watch-application.cpp
--- /dev/null
+/*
+ * Copyright (c) 2022 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/adaptor/common/framework.h>
+
+// EXTERNAL INCLUDES
+#include <glib.h>
+#include <cstdio>
+#include <cstring>
+
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/system/common/callback-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+thread_local GMainLoop* gMainLoop{nullptr};
+
+GMainContext* GetMainLoopContext()
+{
+ if(gMainLoop != nullptr)
+ {
+ return g_main_loop_get_context(gMainLoop);
+ }
+ return nullptr;
+}
+
+/**
+ * Impl to hide GLib data members
+ */
+struct Framework::Impl
+{
+ // Constructor
+ Impl(void* data)
+ : mAbortCallBack(nullptr),
+ mCallbackManager(nullptr),
+ mLanguage("NOT_SUPPORTED"),
+ mRegion("NOT_SUPPORTED")
+ {
+ mCallbackManager = CallbackManager::New();
+
+ // In future, may need to change this to have own context or use Tizen context
+ gMainLoop = mMainLoop = g_main_loop_new(nullptr, false);
+ }
+
+ ~Impl()
+ {
+ delete mAbortCallBack;
+
+ // we're quiting the main loop so
+ // mCallbackManager->RemoveAllCallBacks() does not need to be called
+ // to delete our abort handler
+ delete mCallbackManager;
+
+ g_main_loop_unref(mMainLoop);
+ gMainLoop = nullptr;
+ }
+
+ void Run()
+ {
+ g_main_loop_run(mMainLoop);
+ }
+
+ void Quit()
+ {
+ g_main_loop_quit(mMainLoop);
+ }
+
+ // Data
+ CallbackBase* mAbortCallBack;
+ CallbackManager* mCallbackManager;
+ GMainLoop* mMainLoop{nullptr};
+ GMainContext* mContext{nullptr};
+
+ std::string mLanguage;
+ std::string mRegion;
+
+private:
+ Impl(const Impl& impl) = delete;
+ Impl& operator=(const Impl& impl) = delete;
+};
+
+Framework::Framework(Framework::Observer& observer, TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)
+: mObserver(observer),
+ mTaskObserver(taskObserver),
+ mInitialised(false),
+ mRunning(false),
+ mArgc(argc),
+ mArgv(argv),
+ mBundleName(""),
+ mBundleId(""),
+ mAbortHandler(MakeCallback(this, &Framework::AbortCallback)),
+ mImpl(NULL)
+{
+ mImpl = new Impl(this);
+}
+
+Framework::~Framework()
+{
+ if(mRunning)
+ {
+ Quit();
+ }
+
+ delete mImpl;
+}
+
+void Framework::Run()
+{
+ mRunning = true;
+ mObserver.OnInit();
+ mImpl->Run();
+
+ mRunning = false;
+}
+
+void Framework::Quit()
+{
+ mObserver.OnTerminate();
+ mImpl->Quit();
+}
+
+bool Framework::IsMainLoopRunning()
+{
+ return mRunning;
+}
+
+void Framework::AddAbortCallback(CallbackBase* callback)
+{
+ mImpl->mAbortCallBack = callback;
+}
+
+std::string Framework::GetBundleName() const
+{
+ return mBundleName;
+}
+
+void Framework::SetBundleName(const std::string& name)
+{
+}
+
+std::string Framework::GetBundleId() const
+{
+ return "";
+}
+
+std::string Framework::GetResourcePath()
+{
+ // "DALI_APPLICATION_PACKAGE" is used by Ubuntu specifically to get the already configured Application package path.
+ const char* ubuntuEnvironmentVariable = "DALI_APPLICATION_PACKAGE";
+ char* value = getenv(ubuntuEnvironmentVariable);
+ std::string resourcePath;
+ if(value != NULL)
+ {
+ resourcePath = value;
+ }
+
+ if(resourcePath.back() != '/')
+ {
+ resourcePath += "/";
+ }
+
+ return resourcePath;
+}
+
+void Framework::SetBundleId(const std::string& id)
+{
+}
+
+void Framework::AbortCallback()
+{
+ // if an abort call back has been installed run it.
+ if(mImpl->mAbortCallBack)
+ {
+ CallbackBase::Execute(*mImpl->mAbortCallBack);
+ }
+ else
+ {
+ Quit();
+ }
+}
+
+bool Framework::AppStatusHandler(int type, void* bundleData)
+{
+ return true;
+}
+
+std::string Framework::GetLanguage() const
+{
+ return mImpl->mLanguage;
+}
+
+std::string Framework::GetRegion() const
+{
+ return mImpl->mRegion;
+}
+
+std::string Framework::GetDataPath()
+{
+ const char* ubuntuEnvironmentVariable = "DALI_APPLICATION_DATA_DIR";
+ char* value = getenv(ubuntuEnvironmentVariable);
+ std::string dataPath;
+ if(value != NULL)
+ {
+ dataPath = value;
+ }
+
+ return dataPath;
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
SET( adaptor_clipboard_libuv_x11_src_files
${adaptor_clipboard_dir}/generic/clipboard-impl-generic.cpp
)
+
+# module: clipboard, backend: glib-x11
+SET( adaptor_clipboard_glib_x11_src_files
+ ${adaptor_clipboard_dir}/generic/clipboard-impl-generic.cpp
+)
${adaptor_system_dir}/ubuntu-x11/widget-controller-x.cpp
)
+# module: system, backend: glib-x11
+SET( adaptor_system_glib_src_files
+ ${adaptor_system_dir}/common/shared-file.cpp
+ ${adaptor_system_dir}/common/time-service.cpp
+ ${adaptor_system_dir}/common/trigger-event.cpp
+ ${adaptor_system_dir}/common/trigger-event-factory.cpp
+ ${adaptor_system_dir}/generic/shared-file-operations-generic.cpp
+ ${adaptor_system_dir}/glib/callback-manager-glib.cpp
+ ${adaptor_system_dir}/glib/file-descriptor-monitor-glib.cpp
+ ${adaptor_system_dir}/glib/timer-impl-glib.cpp
+ ${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}/ubuntu-x11/widget-controller-x.cpp
+)
# module: system, backend: android
SET( adaptor_system_android_src_files
--- /dev/null
+/*
+ * Copyright (c) 2022 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/glib/callback-manager-glib.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <glib.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+extern GMainContext* GetMainLoopContext();
+
+/**
+ * Structure contains the callback function and control options
+ */
+struct CallbackData
+{
+ typedef gboolean (*CallbackFunction)(gpointer userData);
+
+ /**
+ * Constructor
+ */
+ CallbackData(CallbackBase* callback, bool hasReturnValue)
+ : mCallback(callback),
+ mHasReturnValue(hasReturnValue)
+ {
+ }
+
+ /**
+ * Add the idle callback
+ */
+ void AddIdle()
+ {
+ GMainContext* context = GetMainLoopContext();
+ if(context != nullptr)
+ {
+ mSource = g_idle_source_new();
+ g_source_set_priority(mSource, G_PRIORITY_HIGH_IDLE);
+ g_source_set_callback(mSource, &CallbackData::IdleCallback, this, nullptr); // No destroyNotify
+ guint id = g_source_attach(mSource, context);
+ }
+ }
+
+ /**
+ * Destructor
+ */
+ ~CallbackData()
+ {
+ g_source_destroy(mSource);
+ g_source_unref(mSource);
+ mSource = nullptr;
+
+ delete mCallback;
+ delete mRemoveFromContainerFunction;
+ }
+
+ static gboolean IdleCallback(gpointer userData)
+ {
+ gboolean retValue = G_SOURCE_REMOVE;
+ CallbackData* callbackData = static_cast<CallbackData*>(userData);
+
+ if(callbackData->mHasReturnValue)
+ {
+ // run the function
+ bool cont = CallbackBase::ExecuteReturn<bool>(*callbackData->mCallback);
+ if(!cont)
+ {
+ // remove callback data from the container
+ CallbackBase::Execute(*callbackData->mRemoveFromContainerFunction, callbackData);
+ // will clear up the handle
+ delete callbackData;
+ }
+ else
+ {
+ retValue = G_SOURCE_CONTINUE;
+ }
+ }
+ else
+ {
+ // remove callback data from the container first in case our callback tries to modify the container
+ CallbackBase::Execute(*callbackData->mRemoveFromContainerFunction, callbackData);
+
+ // run the function
+ CallbackBase::Execute(*callbackData->mCallback);
+
+ // will clear up the handle
+ delete callbackData;
+ }
+ return retValue;
+ }
+
+ // Data
+ CallbackBase* mCallback; ///< call back
+ CallbackBase* mRemoveFromContainerFunction{nullptr}; ///< Called to remove the callbackdata from the callback container
+ GSource* mSource{nullptr}; ///< idle handle
+ bool mExecute{true}; ///< whether to run the callback
+ bool mHasReturnValue{false}; ///< true if the callback function has a return value.
+};
+
+GlibCallbackManager::GlibCallbackManager()
+: mRunning(false)
+{
+}
+
+void GlibCallbackManager::Start()
+{
+ DALI_ASSERT_DEBUG(mRunning == false);
+ mRunning = true;
+}
+
+void GlibCallbackManager::Stop()
+{
+ // make sure we're not called twice
+ DALI_ASSERT_DEBUG(mRunning == true);
+
+ mRunning = false;
+
+ for(CallbackList::iterator iter = mCallbackContainer.begin(); iter != mCallbackContainer.end(); ++iter)
+ {
+ CallbackData* data = (*iter);
+
+ delete data;
+ }
+ mCallbackContainer.clear();
+}
+
+bool GlibCallbackManager::AddIdleCallback(CallbackBase* callback, bool hasReturnValue)
+{
+ if(!mRunning)
+ {
+ return false;
+ }
+
+ CallbackData* callbackData = new CallbackData(callback, hasReturnValue);
+
+ // To inform the manager a callback has finished, we get it to call RemoveCallbackFromContainer
+ callbackData->mRemoveFromContainerFunction = MakeCallback(this, &GlibCallbackManager::RemoveCallbackFromContainer);
+
+ // add the call back to the container
+ mCallbackContainer.push_front(callbackData);
+
+ // init the callback
+ callbackData->AddIdle();
+
+ return true;
+}
+
+void GlibCallbackManager::RemoveIdleCallback(CallbackBase* callback)
+{
+ for(CallbackList::iterator it = mCallbackContainer.begin(),
+ endIt = mCallbackContainer.end();
+ it != endIt;
+ ++it)
+ {
+ CallbackData* data = *it;
+
+ if(data->mCallback == callback)
+ {
+ // remove callback data from the container.
+ CallbackBase::Execute(*data->mRemoveFromContainerFunction, data);
+
+ delete data;
+ }
+ }
+}
+
+bool GlibCallbackManager::ProcessIdle()
+{
+ // TBD
+ return false;
+}
+
+void GlibCallbackManager::ClearIdleCallbacks()
+{
+ // TBD
+}
+
+bool GlibCallbackManager::AddIdleEntererCallback(CallbackBase* callback)
+{
+ if(!mRunning)
+ {
+ return false;
+ }
+
+ CallbackData* callbackData = new CallbackData(callback, true);
+
+ // To inform the manager a callback has finished, we get it to call RemoveCallbackFromContainer
+ callbackData->mRemoveFromContainerFunction = MakeCallback(this, &GlibCallbackManager::RemoveCallbackFromContainer);
+
+ // add the call back to the front of the container
+ mCallbackContainer.push_front(callbackData);
+
+ // init the callback
+ callbackData->AddIdle();
+
+ return true;
+}
+
+void GlibCallbackManager::RemoveIdleEntererCallback(CallbackBase* callback)
+{
+ RemoveIdleCallback(callback);
+}
+
+void GlibCallbackManager::RemoveCallbackFromContainer(CallbackData* callbackData)
+{
+ mCallbackContainer.remove(callbackData);
+}
+
+// Creates a concrete interface for CallbackManager
+CallbackManager* CallbackManager::New()
+{
+ return new GlibCallbackManager;
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_ADAPTOR_GLIB_CALLBACK_MANAGER_H
+#define DALI_ADAPTOR_GLIB_CALLBACK_MANAGER_H
+
+/*
+ * Copyright (c) 2022 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 <list>
+
+// INTERNAL INCLUDES
+#include <dali/internal/system/common/callback-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+struct CallbackData;
+
+/**
+ * @brief Glib callback manager used to install call backs in the applications main loop.
+ * The manager keeps track of all callbacks, so that if Stop() is called it can remove them.
+ */
+class GlibCallbackManager : public CallbackManager
+{
+public:
+ /**
+ * @brief constructor
+ */
+ GlibCallbackManager();
+
+ /**
+ * @brief destructor
+ */
+ virtual ~GlibCallbackManager() = default;
+
+ /**
+ * @copydoc CallbackManager::AddIdleCallback()
+ */
+ bool AddIdleCallback(CallbackBase* callback, bool hasReturnValue) override;
+
+ /**
+ * @copydoc 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;
+
+private:
+ /**
+ * @brief Removes a single call back from the container
+ * Always called from main thread
+ * @param callbackData callback data
+ */
+ void RemoveCallbackFromContainer(CallbackData* callbackData);
+
+ typedef std::list<CallbackData*> CallbackList; ///< list of callbacks installed
+
+ bool mRunning; ///< flag is set to true if when running
+ CallbackList mCallbackContainer; ///< container of live callbacks
+};
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_ADAPTOR_GLIB_CALLBACK_MANAGER_H
--- /dev/null
+/*
+ * Copyright (c) 2022 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>
+#include <glib-unix.h>
+#include <glib.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+extern GMainContext* GetMainLoopContext();
+
+/**
+ * Using Impl to hide away framework specific members
+ */
+struct FileDescriptorMonitor::Impl
+{
+public:
+ // Constructor
+ Impl(int fileDescriptor, CallbackBase* callback, GIOCondition eventsToMonitor)
+ : mFileDescriptor(fileDescriptor),
+ mEventsToMonitor(eventsToMonitor),
+ mCallback(callback),
+ mPollSource(nullptr)
+ {
+ mPollSource = g_unix_fd_source_new(fileDescriptor, eventsToMonitor);
+ g_source_set_callback(mPollSource, reinterpret_cast<GSourceFunc>(PollCallback), this, nullptr);
+ g_source_attach(mPollSource, GetMainLoopContext());
+ }
+
+ ~Impl()
+ {
+ g_source_destroy(mPollSource);
+ g_source_unref(mPollSource);
+ mPollSource = nullptr;
+
+ delete mCallback;
+ }
+
+ static gboolean PollCallback(int fileDescriptor, GIOCondition events, gpointer userData)
+ {
+ if(userData)
+ {
+ FileDescriptorMonitor::Impl* impl = static_cast<FileDescriptorMonitor::Impl*>(userData);
+
+ // filter the events that have occured based on what we are monitoring
+ int eventType = FileDescriptorMonitor::FD_NO_EVENT;
+
+ if((impl->mEventsToMonitor & G_IO_IN) && (events & G_IO_IN))
+ {
+ eventType = FileDescriptorMonitor::FD_READABLE;
+ }
+ if((impl->mEventsToMonitor & G_IO_OUT) && (events & G_IO_OUT))
+ {
+ eventType |= FileDescriptorMonitor::FD_WRITABLE;
+ }
+
+ // if there is an event, execute the callback
+ if(eventType != FileDescriptorMonitor::FD_NO_EVENT)
+ {
+ CallbackBase::Execute(*impl->mCallback, static_cast<FileDescriptorMonitor::EventType>(eventType));
+ }
+ }
+ return G_SOURCE_CONTINUE;
+ }
+ // Data
+ int mFileDescriptor;
+ GIOCondition mEventsToMonitor;
+ CallbackBase* mCallback;
+ GSource* mPollSource;
+};
+
+FileDescriptorMonitor::FileDescriptorMonitor(int fileDescriptor, CallbackBase* callback, int eventBitmask)
+{
+ if(fileDescriptor < 1)
+ {
+ DALI_ASSERT_ALWAYS(0 && "Invalid File descriptor");
+ return;
+ }
+ GIOCondition events = static_cast<GIOCondition>(0);
+ if(eventBitmask & FD_READABLE)
+ {
+ events = G_IO_IN;
+ }
+ if(eventBitmask & FD_WRITABLE)
+ {
+ events = static_cast<GIOCondition>(static_cast<int>(events) | G_IO_OUT);
+ }
+
+ DALI_ASSERT_ALWAYS(events && "Invalid FileDescriptorMonitor event type ");
+
+ // waiting for a write event on a file descriptor
+ mImpl = new Impl(fileDescriptor, callback, static_cast<GIOCondition>(events));
+}
+
+FileDescriptorMonitor::~FileDescriptorMonitor()
+{
+ delete mImpl;
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+/*
+ * Copyright (c) 2022 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>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/system/common/time-service.h>
+
+// EXTERNAL INCLUDES
+#include <glib.h>
+#include <sys/time.h>
+
+namespace Dali::Internal::Adaptor
+{
+extern GMainContext* GetMainLoopContext();
+
+namespace
+{
+gboolean TimerSourceFunc(gpointer userData)
+{
+ Timer* timer = static_cast<Timer*>(userData);
+
+ bool keepRunning = timer->Tick();
+ return keepRunning ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE;
+}
+
+} // unnamed namespace
+
+struct Timer::Impl
+{
+ Impl(unsigned int milliSec)
+ : mInterval(milliSec)
+ {
+ }
+
+ GSource* mTimerHandle{nullptr};
+ unsigned int mInterval{0};
+ uint32_t mStartTimestamp{0};
+ uint32_t mPauseTimestamp{0};
+ bool mRunning{false};
+ bool mRestartAfterExpiry{false}; // Restart at full interval after pause/resume/expiry
+};
+
+TimerPtr Timer::New(unsigned int milliSec)
+{
+ TimerPtr timer(new Timer(milliSec));
+ return timer;
+}
+
+Timer::Timer(unsigned int milliSec)
+: mImpl(new Impl(milliSec))
+{
+}
+
+Timer::~Timer()
+{
+ Stop();
+ delete mImpl;
+}
+
+void Timer::Start()
+{
+ if(mImpl->mRunning && mImpl->mTimerHandle)
+ {
+ Stop();
+ }
+
+ mImpl->mTimerHandle = g_timeout_source_new(mImpl->mInterval);
+ g_source_set_callback(mImpl->mTimerHandle, TimerSourceFunc, this, nullptr); // user data is this object, no need for destroy notify.
+ g_source_attach(mImpl->mTimerHandle, GetMainLoopContext());
+
+ mImpl->mRunning = true;
+ mImpl->mStartTimestamp = TimeService::GetMilliSeconds();
+}
+
+void Timer::Stop()
+{
+ if(mImpl->mTimerHandle != nullptr)
+ {
+ g_source_destroy(mImpl->mTimerHandle);
+ g_source_unref(mImpl->mTimerHandle);
+ mImpl->mTimerHandle = nullptr;
+
+ mImpl->mStartTimestamp = 0;
+ mImpl->mPauseTimestamp = 0;
+ }
+
+ ResetTimerData();
+}
+
+void Timer::Pause()
+{
+ if(mImpl->mRunning)
+ {
+ g_source_destroy(mImpl->mTimerHandle);
+ g_source_unref(mImpl->mTimerHandle);
+ mImpl->mTimerHandle = nullptr;
+ mImpl->mPauseTimestamp = TimeService::GetMilliSeconds();
+ }
+}
+
+void Timer::Resume()
+{
+ if(mImpl->mRunning && mImpl->mTimerHandle == nullptr)
+ {
+ uint32_t newInterval = 0;
+ uint32_t runningTime = mImpl->mPauseTimestamp - mImpl->mStartTimestamp;
+ if(mImpl->mInterval > runningTime)
+ {
+ newInterval = mImpl->mInterval - runningTime;
+ }
+
+ mImpl->mStartTimestamp = TimeService::GetMilliSeconds() - runningTime;
+ mImpl->mPauseTimestamp = 0;
+
+ mImpl->mTimerHandle = g_timeout_source_new(newInterval);
+ g_source_set_callback(mImpl->mTimerHandle, TimerSourceFunc, this, nullptr);
+ g_source_attach(mImpl->mTimerHandle, GetMainLoopContext());
+ // After next expiry, stop and restart with correct interval
+ mImpl->mRestartAfterExpiry = true;
+ }
+}
+
+void Timer::SetInterval(unsigned int interval, bool restart)
+{
+ // stop existing timer
+ Stop();
+ mImpl->mInterval = interval;
+
+ if(restart)
+ {
+ // start new tick
+ Start();
+ }
+}
+
+unsigned int Timer::GetInterval() const
+{
+ return mImpl->mInterval;
+}
+
+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;
+ }
+
+ if(mImpl->mRestartAfterExpiry && mImpl->mRunning)
+ {
+ mImpl->mRestartAfterExpiry = false;
+ // Timer was resumed.
+ retVal = false;
+ ResetTimerData();
+ Start();
+ }
+
+ return retVal;
+}
+
+Dali::Timer::TimerSignalType& Timer::TickSignal()
+{
+ return mTickSignal;
+}
+
+void Timer::ResetTimerData()
+{
+ mImpl->mRunning = false;
+ if(mImpl->mTimerHandle)
+ {
+ g_source_unref(mImpl->mTimerHandle);
+ }
+ mImpl->mTimerHandle = nullptr;
+}
+
+bool Timer::IsRunning() const
+{
+ return mImpl->mRunning;
+}
+
+} // namespace Dali::Internal::Adaptor
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
switch(level)
{
case Dali::Integration::Log::DebugInfo:
- format = "\e[1;34mINFO:\e[21m %s: %s\e[0m";
+ format = "\e[1;32mINFO:\e[21m %s: %s\e[0m";
break;
case Dali::Integration::Log::DebugWarning:
format = "\e[1;33mWARN:\e[21m %s: %s\e[0m";
#include <unordered_map>
#include <vector>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
namespace Dali
{
namespace Internal
mXEventMonitor = new FileDescriptorMonitor(
ConnectionNumber(mDisplay),
MakeCallback(this, &WindowSystemX::Impl::XPollCallback),
- (FileDescriptorMonitor::FD_READABLE | FileDescriptorMonitor::FD_WRITABLE));
+ FileDescriptorMonitor::FD_READABLE);
+ // libuv hacks: add FD_WRITABLE.
InitializeAtoms();
SetupEventHandlers();