--- /dev/null
+#ifndef __DALI_INTERNAL_BASE_WINDOW_EVENT_INTERFACE_H__
+#define __DALI_INTERNAL_BASE_WINDOW_EVENT_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/events/touch-point.h>
+#include <dali/public-api/events/key-event.h>
+#include <dali/public-api/events/wheel-event.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * @brief Abstract interface for handling DALi events received from the native window system
+ *
+ */
+class WindowEventInterface
+{
+
+public:
+
+ /**
+ * @brief Touch Event callback
+ * @param[in] point touch point
+ * @param[in] timeStamp time stamp
+ */
+ virtual void TouchEvent( Dali::TouchPoint& point, unsigned long timeStamp ) = 0;
+
+ /**
+ * @brief Key Event callback
+ * @param[in] keyEvent key event
+ */
+ virtual void KeyEvent( Dali::KeyEvent& keyEvent ) = 0;
+
+ /**
+ * @brief Wheel Event callback
+ * @param[in] wheelEvent wheel event
+ */
+ virtual void WheelEvent( Dali::WheelEvent& wheelEvent ) = 0;
+
+ /**
+ * @brief Window damage callback
+ * @param[in] damageArea Window damage area
+ */
+ virtual void DamageEvent( Dali::Rect<int>& damageArea ) = 0;
+
+ /**
+ * @brief Window Focused
+ */
+ virtual void WindowFocusIn() = 0;
+
+ /**
+ * @brief Window lost focus
+ */
+ virtual void WindowFocusOut() = 0;
+
+protected:
+
+ /**
+ * @brief Constructor
+ */
+ WindowEventInterface()
+ {
+ }
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~WindowEventInterface()
+ {
+ }
+
+ // Undefined copy constructor.
+ WindowEventInterface( const WindowEventInterface& );
+
+ // Undefined assignment operator.
+ WindowEventInterface& operator=( const WindowEventInterface& );
+
+};
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_BASE_WINDOW_EVENT_INTERFACE_H__
return gThreadLocalAdaptor != NULL;
}
+void Adaptor::SceneCreated()
+{
+ mCore->SceneCreated();
+}
+
Dali::Integration::Core& Adaptor::GetCore()
{
return *mCore;
*/
static bool IsAvailable();
+ /**
+ * @copydoc Dali::Core::SceneCreated();
+ */
+ void SceneCreated();
+
public: // AdaptorInternalServices implementation
/**
* @copydoc Dali::Adaptor::Start()
mImpl->FeedKeyEvent(keyEvent);
}
+void Adaptor::SceneCreated()
+{
+ mImpl->SceneCreated();
+}
+
+void Adaptor::SetViewMode( ViewMode mode )
+{
+ mImpl->SetViewMode( mode );
+}
+
+void Adaptor::SetStereoBase( float stereoBase )
+{
+ mImpl->SetStereoBase( stereoBase );
+}
+
+
Adaptor::Adaptor()
: mImpl( NULL )
{
public:
- /**
- * constructor
+ /**
+ * @brief constructor
*/
EcoreCallbackManager();
/**
- * destructor
+ * @brief destructor
*/
~EcoreCallbackManager()
{
private:
/**
- * Remove all idle call backs that are pending
+ * @brief Remove all idle call backs that are pending
* Called by Stop()
* Always called from the main thread
*/
void RemoveAllCallbacks();
/**
- * Removes a single call back from the container
+ * @brief Removes a single call back from the container
* Always called from main thread
* @param callbackData callback data
*/
void RemoveCallbackFromContainer(CallbackData *callbackData);
/**
- * Remove a standard call back from ecore
+ * @brief Remove a standard call back from ecore
* Always called from main thread
* @param callbackData callback data
*/
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "uv-callback-manager.h"
+
+// EXTERNAL INCLUDES
+#include <uv.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+
+static void FreeHandleCallback(uv_handle_t* handle )
+{
+ delete handle;
+}
+
+}
+/**
+ * Structure contains the callback function and control options
+ */
+struct CallbackData
+{
+ typedef void (*CallbackFunction)(uv_idle_t*);
+
+ /**
+ * Constructor
+ */
+ CallbackData( CallbackBase* callback )
+ : mCallback(callback),
+ mRemoveFromContainerFunction(NULL),
+ mIdleHandle( NULL),
+ mExecute(true)
+ {
+ }
+
+ /**
+ * Add the idle callback
+ */
+ void AddIdle( CallbackFunction callback)
+ {
+ // heap allocate a handle as it will be alive after the CallbackData object is deleted.
+ mIdleHandle = new uv_idle_t;
+
+ // Node.JS uses uv_default_loop
+ uv_idle_init( uv_default_loop() , mIdleHandle );
+
+ mIdleHandle->data = this;
+
+ uv_idle_start( mIdleHandle, callback);
+ }
+
+ /**
+ * Destructor
+ */
+ ~CallbackData()
+ {
+ // the handle will still be alive for a short period after calling uv_close
+ // set the data to NULL to avoid a dangling pointer
+ mIdleHandle->data = NULL;
+
+ uv_idle_stop( mIdleHandle );
+
+ uv_close( reinterpret_cast< uv_handle_t*>( mIdleHandle ) , FreeHandleCallback );
+
+ delete mCallback;
+ delete mRemoveFromContainerFunction;
+ }
+
+ // Data
+ CallbackBase* mCallback; ///< call back
+ CallbackBase* mRemoveFromContainerFunction; ///< Called to remove the callbackdata from the callback container
+ uv_idle_t* mIdleHandle; ///< idle handle
+ bool mExecute; ///< whether to run the callback
+
+};
+
+namespace
+{
+void IdleCallback( uv_idle_t* handle )
+{
+ CallbackData *callbackData = static_cast<CallbackData *>(handle->data);
+
+ // 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;
+
+}
+}
+
+UvCallbackManager::UvCallbackManager()
+:mRunning(false)
+{
+}
+
+void UvCallbackManager::Start()
+{
+ DALI_ASSERT_DEBUG( mRunning == false );
+ mRunning = true;
+}
+
+void UvCallbackManager::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 UvCallbackManager::AddIdleCallback( CallbackBase* callback )
+{
+ if( !mRunning )
+ {
+ return false;
+ }
+
+ CallbackData *callbackData = new CallbackData(callback );
+
+ // To inform the manager a callback has finished, we get it to call RemoveCallbackFromContainer
+ callbackData->mRemoveFromContainerFunction = MakeCallback( this, &UvCallbackManager::RemoveCallbackFromContainer );
+
+ // add the call back to the container
+ mCallbackContainer.push_front(callbackData);
+
+ // init the callback
+ callbackData->AddIdle( &IdleCallback );
+
+ return true;
+}
+
+void UvCallbackManager::RemoveCallbackFromContainer(CallbackData *callbackData)
+{
+ mCallbackContainer.remove(callbackData);
+}
+
+// Creates a concrete interface for CallbackManager
+CallbackManager* CallbackManager::New()
+{
+ return new UvCallbackManager;
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_UV_CALLBACK_MANAGER_H__
+#define __DALI_UV_CALLBACK_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <list>
+
+// INTERNAL INCLUDES
+#include <callback-manager.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+struct CallbackData;
+
+/**
+ * @brief LibUV 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 UvCallbackManager : public CallbackManager
+{
+
+public:
+
+ /**
+ * @brief constructor
+ */
+ UvCallbackManager();
+
+ /**
+ * @brief destructor
+ */
+ ~UvCallbackManager(){}
+
+ /**
+ * @copydoc CallbackManager::AddCallback()
+ */
+ virtual bool AddIdleCallback( CallbackBase* callback );
+
+ /**
+ * @copydoc CallbackManager::Start()
+ */
+ virtual void Start();
+
+ /**
+ * @copydoc CallbackManager::Stop()
+ */
+ virtual void Stop();
+
+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_UV_CALLBACK_MANAGER_H__
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "file-descriptor-monitor.h"
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <uv.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+void FreeHandleCallback(uv_handle_t* handle )
+{
+ delete handle;
+}
+
+}
+
+/**
+ * Using Impl to hide away UV specific members
+ */
+struct FileDescriptorMonitor::Impl
+{
+public:
+
+ // Constructor
+ Impl( int fileDescriptor, CallbackBase* callback )
+ : mFileDescriptor( fileDescriptor ),
+ mCallback( callback ),
+ pollHandle( NULL )
+ {
+
+ // heap allocate a handle as it will be alive after the FileDescriptorMonitor::Impl object is deleted.
+ pollHandle = new uv_poll_t;
+
+ // Node.JS uses uv_default_loop
+ uv_poll_init( uv_default_loop(), pollHandle, fileDescriptor);
+
+ pollHandle->data = this;
+
+ uv_poll_start( pollHandle, UV_READABLE, PollCabllack);
+ }
+
+ ~Impl()
+ {
+ uv_poll_stop( pollHandle );
+
+ // the handle will still be alive for a short period after calling uv_close
+ // set the data to NULL to avoid a dangling pointer
+ pollHandle->data = NULL;
+
+ uv_close(reinterpret_cast<uv_handle_t*> ( pollHandle ) , FreeHandleCallback );
+
+ delete mCallback;
+ }
+
+ static void PollCabllack(uv_poll_t* handle, int status, int events)
+ {
+ if( handle->data )
+ {
+ FileDescriptorMonitor::Impl* impl= static_cast<FileDescriptorMonitor::Impl* >(handle->data);
+ // run the function
+ CallbackBase::Execute( *impl->mCallback );
+ }
+ }
+ // Data
+ int mFileDescriptor;
+ CallbackBase* mCallback;
+ uv_poll_t* pollHandle;
+
+};
+
+
+FileDescriptorMonitor::FileDescriptorMonitor( int fileDescriptor, CallbackBase* callback )
+{
+ if (fileDescriptor < 0)
+ {
+ return;
+ }
+
+ // waiting for a write event on a file descriptor
+ mImpl = new Impl(fileDescriptor, callback);
+}
+
+FileDescriptorMonitor::~FileDescriptorMonitor()
+{
+ delete mImpl;
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "timer-impl.h"
+#include <dali/integration-api/debug.h>
+
+// EXTERNAL INCLUDES
+#include <uv.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+void TimerSourceFunc (uv_timer_t* handle)
+{
+ Timer* timer = static_cast<Timer*>(handle->data);
+
+ bool keepRunning = timer->Tick();
+ if( !keepRunning )
+ {
+ timer->Stop();
+ }
+}
+void FreeHandleCallback(uv_handle_t* handle )
+{
+ delete handle;
+}
+
+} // unnamed namespace
+
+/**
+ * Struct to hide away Ecore implementation details
+ */
+struct Timer::Impl
+{
+ Impl( unsigned int milliSec )
+ : mTimerHandle( NULL ),
+ mInterval( milliSec ),
+ mRunning( false )
+ {
+ }
+
+ ~Impl()
+ {
+ // the handle will still be alive for a short period after calling uv_close
+ // set the data to NULL to avoid a dangling pointer
+ mTimerHandle->data = NULL;
+
+ uv_close( reinterpret_cast< uv_handle_t* >( mTimerHandle ), FreeHandleCallback );
+ }
+
+ bool Running()
+ {
+ return mRunning;
+ }
+
+ void Start( void* internalTimerPtr )
+ {
+ Stop(); // make sure we stop first if its currently running
+
+ if( !mTimerHandle )
+ {
+ // heap allocate the handle as its lifetime will be longer than TimerImpl
+ mTimerHandle = new uv_timer_t;
+
+ // initialize the handle
+ uv_timer_init( uv_default_loop(), mTimerHandle);
+ }
+
+ mRunning = true;
+
+ mTimerHandle->data = internalTimerPtr;
+
+ uv_timer_start( mTimerHandle, TimerSourceFunc, mInterval, mInterval);
+ }
+
+ void Stop()
+ {
+ if( mRunning )
+ {
+ mTimerHandle->data = NULL;
+ uv_timer_stop( mTimerHandle );
+ mRunning = false;
+ }
+ }
+
+ uv_timer_t* mTimerHandle;
+ unsigned int mInterval;
+ bool mRunning;
+};
+
+TimerPtr Timer::New( unsigned int milliSec )
+{
+ DALI_LOG_ERROR(" new timer");
+ TimerPtr timer( new Timer( milliSec ) );
+ return timer;
+}
+
+Timer::Timer( unsigned int milliSec )
+: mImpl(new Impl(milliSec))
+{
+}
+
+Timer::~Timer()
+{
+ // stop timers
+ Stop();
+
+ delete mImpl;
+}
+
+void Timer::Start()
+{
+ mImpl->Start( this );
+}
+
+void Timer::Stop()
+{
+ mImpl->Stop();
+}
+
+void Timer::SetInterval( unsigned int interval )
+{
+ // stop existing timer
+ Stop();
+
+ mImpl->mInterval = interval;
+
+ // 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;
+ }
+
+ return retVal;
+}
+
+Dali::Timer::TimerSignalType& Timer::TickSignal()
+{
+ return mTickSignal;
+}
+
+bool Timer::IsRunning() const
+{
+ return mImpl->mRunning;
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
$(adaptor_common_dir)/clipboard-event-notifier-impl.cpp \
$(adaptor_common_dir)/command-line-options.cpp \
$(adaptor_common_dir)/drag-and-drop-detector-impl.cpp \
- $(adaptor_common_dir)/ecore-callback-manager.cpp \
- $(adaptor_common_dir)/file-descriptor-monitor.cpp \
$(adaptor_common_dir)/haptic-player-impl.cpp \
$(adaptor_common_dir)/indicator-impl.cpp \
$(adaptor_common_dir)/indicator-buffer.cpp \
$(adaptor_common_dir)/singleton-service-impl.cpp \
$(adaptor_common_dir)/sound-player-impl.cpp \
$(adaptor_common_dir)/style-monitor-impl.cpp \
- $(adaptor_common_dir)/timer-impl.cpp \
$(adaptor_common_dir)/trigger-event.cpp \
$(adaptor_common_dir)/trigger-event-factory.cpp \
$(adaptor_common_dir)/virtual-keyboard-impl.cpp \
$(adaptor_common_dir)/gl/gl-proxy-implementation.cpp \
$(adaptor_common_dir)/gl/gl-extensions.cpp
+# Different files depending on the event loop being used
+adaptor_common_internal_ecore_src_files = \
+ $(adaptor_common_dir)/event-loop/ecore/ecore-callback-manager.cpp \
+ $(adaptor_common_dir)/event-loop/ecore/ecore-file-descriptor-monitor.cpp \
+ $(adaptor_common_dir)/event-loop/ecore/ecore-timer-impl.cpp
+
+ adaptor_common_internal_uv_src_files = \
+ $(adaptor_common_dir)/event-loop/lib-uv/uv-callback-manager.cpp \
+ $(adaptor_common_dir)/event-loop/lib-uv/uv-file-descriptor-monitor.cpp \
+ $(adaptor_common_dir)/event-loop/lib-uv/uv-timer-impl.cpp
+
adaptor_common_internal_default_profile_src_files = \
$(adaptor_common_dir)/color-controller-impl.cpp \
$(adaptor_common_dir)/system-settings.cpp
#include "orientation-impl.h"
// EXTERNAL INCLUDES
-#include <Ecore.h>
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
#include <cstring>
-#include <Ecore.h>
namespace Dali
{
bool mStarted:1;
bool mIsTransparent:1;
bool mWMRotationAppSet:1;
+ bool mEcoreEventHander:1;
Indicator* mIndicator;
Dali::Window::WindowOrientation mIndicatorOrientation;
Dali::Window::WindowOrientation mNextIndicatorOrientation;
#include <dali/public-api/signals/dali-signal.h>
#include <dali/public-api/math/rect.h>
#include <dali/public-api/events/touch-event.h>
+#include <dali/public-api/common/view-mode.h>
// INTERNAL INCLUDES
-#include "window.h"
-#include "application-configuration.h"
+
+
+#ifdef DALI_ADAPTOR_COMPILATION // full path doesn't exist until adaptor is installed so we have to use relative
+// @todo Make dali-adaptor code folder structure mirror the folder structure installed to dali-env
+#include <window.h>
+#include <application-configuration.h>
+#else
+#include <dali/public-api/adaptor-framework/window.h>
+#include <dali/public-api/adaptor-framework/application-configuration.h>
+#endif
+
namespace Dali
{
*/
void FeedKeyEvent( KeyEvent& keyEvent );
+ /**
+ * @copydoc Dali::Core::SceneCreated();
+ */
+ void SceneCreated();
+
+ /**
+ * @copydoc Dali::Application::SetViewMode();
+ */
+ void SetViewMode( ViewMode viewMode );
+
+ /**
+ * @copydoc Dali::Application::SetStereoBase();
+ */
+ void SetStereoBase( float stereoBase );
+
public: // Signals
/**
$(adaptor_x11_dir)/server-connection-x.cpp \
$(adaptor_x11_dir)/virtual-keyboard-impl-x.cpp \
$(adaptor_x11_dir)/window-impl-x.cpp \
- $(adaptor_x11_dir)/event-handler-x.cpp \
$(adaptor_x11_dir)/egl-implementation-x.cpp \
$(adaptor_x11_dir)/pixmap-render-surface-x.cpp \
$(adaptor_x11_dir)/ecore-x-render-surface.cpp \
$(adaptor_x11_dir)/window-render-surface-x.cpp \
$(adaptor_x11_dir)/ecore-x-window-interface.cpp
+adaptor_ecore_x_event_handler_internal_src_files = \
+ $(adaptor_x11_dir)/ecore-x-event-handler.cpp
+
+adaptor_uv_x_event_handler_internal_src_files = \
+ $(adaptor_x11_dir)/x-event-handler.cpp \
+ $(adaptor_x11_dir)/x-events/x-event-manager.cpp \
+ $(adaptor_x11_dir)/x-events/x-input2.cpp \
+ $(adaptor_x11_dir)/x-events/x-input2-device.cpp \
+ $(adaptor_x11_dir)/x-events/debug/x-input2-debug.cpp
adaptor_x11_ubuntu_internal_src_files = \
$(_adaptor_x11_internal_src_files)
$(adaptor_x11_dir)/system-settings-x.cpp
devel_api_adaptor_tizen_x11_header_files = \
- $(adaptor_x11_dir)/window-extensions.h
+ $(adaptor_x11_dir)/window-extensions.h
\ No newline at end of file
*/
EventHandler( Window* window )
: mWindow( window ),
- mWindowPropertyHandler( ecore_event_handler_add( ECORE_X_EVENT_WINDOW_PROPERTY, EcoreEventWindowPropertyChanged, this ) ),
- mClientMessagehandler( ecore_event_handler_add( ECORE_X_EVENT_CLIENT_MESSAGE, EcoreEventClientMessage, this ) ),
+ mWindowPropertyHandler( NULL ),
+ mClientMessagehandler( NULL ),
mEcoreWindow( 0 )
{
// store ecore window handle
&tmp, 1);
#endif // DALI_PROFILE_UBUNTU
- ecore_x_input_multi_select( mEcoreWindow );
+ if( mWindow->mEcoreEventHander )
+ {
+ ecore_x_input_multi_select( mEcoreWindow );
+ mWindowPropertyHandler= ecore_event_handler_add( ECORE_X_EVENT_WINDOW_PROPERTY, EcoreEventWindowPropertyChanged, this );
+ mClientMessagehandler = ecore_event_handler_add( ECORE_X_EVENT_CLIENT_MESSAGE, EcoreEventClientMessage, this );
+ }
+
}
/**
mStarted(false),
mIsTransparent(false),
mWMRotationAppSet(false),
+ mEcoreEventHander(true),
mIndicator(NULL),
mIndicatorOrientation(Dali::Window::PORTRAIT),
mNextIndicatorOrientation(Dali::Window::PORTRAIT),
mEventHandler(NULL),
mPreferredOrientation(Dali::Window::PORTRAIT)
{
+
+ // Detect if we're not running in a ecore main loop (e.g. libuv).
+ // Typically ecore_x_init is called by app_efl_main->elm_init
+ // but if we're not using app_efl_main then we have to call it ourselves
+ // This is a hack until we create a pure X Window class
+ if( ecore_x_display_get() == NULL )
+ {
+ mEcoreEventHander = false;
+ ecore_x_init (NULL); // internally calls _ecore_x_input_init
+ }
+
}
Window::~Window()
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <events/event-handler.h>
+
+// EXTERNAL INCLUDES
+#include <uv.h>
+#include <Ecore_X.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/extensions/XI2.h>
+
+#include <cstring>
+
+#include <sys/time.h>
+
+#ifndef DALI_PROFILE_UBUNTU
+#include <vconf.h>
+#include <vconf-keys.h>
+#endif // DALI_PROFILE_UBUNTU
+
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/events/touch-point.h>
+#include <dali/public-api/events/key-event.h>
+#include <dali/public-api/events/wheel-event.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/events/key-event-integ.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/integration-api/events/wheel-event-integ.h>
+
+// INTERNAL INCLUDES
+#include <x-events/x-event-manager.h>
+#include <events/gesture-manager.h>
+#include <window-render-surface.h>
+#include <clipboard-impl.h>
+#include <key-impl.h>
+#include <physical-keyboard-impl.h>
+#include <style-monitor-impl.h>
+#include <base/core-event-interface.h>
+#include <base/interfaces/window-event-interface.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+#if defined(DEBUG_ENABLED)
+namespace
+{
+Integration::Log::Filter* gTouchEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH");
+} // unnamed namespace
+#endif
+
+
+namespace
+{
+
+const unsigned int PRIMARY_TOUCH_BUTTON_ID( 1 );
+
+const unsigned int BYTES_PER_CHARACTER_FOR_ATTRIBUTES = 3;
+
+
+// Copied from x server
+static unsigned int GetCurrentMilliSeconds(void)
+{
+ struct timeval tv;
+
+ struct timespec tp;
+ static clockid_t clockid;
+
+ if (!clockid)
+ {
+#ifdef CLOCK_MONOTONIC_COARSE
+ if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
+ (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
+ {
+ clockid = CLOCK_MONOTONIC_COARSE;
+ }
+ else
+#endif
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+ {
+ clockid = CLOCK_MONOTONIC;
+ }
+ else
+ {
+ clockid = ~0L;
+ }
+ }
+ if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
+ {
+ return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
+ }
+
+ gettimeofday(&tv, NULL);
+ return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+}
+
+} // unnamed namespace
+
+
+struct EventHandler::Impl : public WindowEventInterface
+{
+ // Construction & Destruction
+
+ /**
+ * Constructor
+ */
+ Impl( EventHandler* handler, XID window, Display* display )
+ : mXEventManager(window, display, this),
+ mHandler( handler )
+ {
+ mXEventManager.Initialize();
+ }
+ /**
+ * Destructor
+ */
+ ~Impl()
+ {
+ }
+ // @todo Consider allowing the EventHandler class to inherit from WindowEventInterface directly
+ virtual void TouchEvent( Dali::TouchPoint& point, unsigned long timeStamp )
+ {
+ mHandler->SendEvent( point, timeStamp );
+ }
+ virtual void KeyEvent( Dali::KeyEvent& keyEvent )
+ {
+ mHandler->SendEvent( keyEvent );
+ }
+ virtual void WheelEvent( Dali::WheelEvent& wheelEvent )
+ {
+ mHandler->SendWheelEvent( wheelEvent );
+ }
+ virtual void DamageEvent( Rect<int>& damageArea )
+ {
+ mHandler->SendEvent( damageArea );
+ }
+ virtual void WindowFocusOut( )
+ {
+ // used to do some work with ime
+ }
+ virtual void WindowFocusIn()
+ {
+ // used to do some work with ime
+ }
+
+ // Data
+ XEventManager mXEventManager;
+ EventHandler* mHandler;
+};
+
+EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector )
+: mCoreEventInterface(coreEventInterface),
+ mGestureManager( gestureManager ),
+ mStyleMonitor( StyleMonitor::Get() ),
+ mDamageObserver( damageObserver ),
+ mRotationObserver( NULL ),
+ mDragAndDropDetector( dndDetector ),
+ mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
+ mClipboard(Clipboard::Get()),
+ mImpl( NULL )
+{
+ Ecore_X_Window window = 0;
+
+ // this code only works with the EcoreX11 RenderSurface so need to downcast
+ ECore::WindowRenderSurface* ecoreSurface = dynamic_cast< ECore::WindowRenderSurface* >( surface );
+ if( ecoreSurface )
+ {
+ window = ecoreSurface->GetXWindow();
+ Display* display = static_cast< Display* >(ecore_x_display_get());
+
+ mImpl = new Impl(this, window, display );
+
+ }
+
+}
+
+EventHandler::~EventHandler()
+{
+ if(mImpl)
+ {
+ delete mImpl;
+ }
+
+ mGestureManager.Stop();
+}
+
+void EventHandler::SendEvent(TouchPoint& point, unsigned long timeStamp)
+{
+ if(timeStamp < 1)
+ {
+ timeStamp = GetCurrentMilliSeconds();
+ }
+
+ Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
+ Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
+ if(type != Integration::TouchEventCombiner::DispatchNone )
+ {
+ DALI_LOG_INFO(gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.deviceId, point.state, point.local.x, point.local.y);
+
+ // First the touch and/or hover event & related gesture events are queued
+ if(type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth)
+ {
+ mCoreEventInterface.QueueCoreEvent( touchEvent );
+ mGestureManager.SendEvent(touchEvent);
+ }
+
+ if(type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth)
+ {
+ mCoreEventInterface.QueueCoreEvent( hoverEvent );
+ }
+
+ // Next the events are processed with a single call into Core
+ mCoreEventInterface.ProcessCoreEvents();
+ }
+}
+
+void EventHandler::SendEvent(KeyEvent& keyEvent)
+{
+ Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
+ if ( physicalKeyboard )
+ {
+ if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ) )
+ {
+ GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
+ }
+ }
+
+ // Create KeyEvent and send to Core.
+ Integration::KeyEvent event(keyEvent.keyPressedName, keyEvent.keyPressed, keyEvent.keyCode,
+ keyEvent.keyModifier, keyEvent.time, static_cast<Integration::KeyEvent::State>(keyEvent.state));
+ mCoreEventInterface.QueueCoreEvent( event );
+ mCoreEventInterface.ProcessCoreEvents();
+}
+
+void EventHandler::SendWheelEvent( WheelEvent& wheelEvent )
+{
+ // Create WheelEvent and send to Core.
+ Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
+ mCoreEventInterface.QueueCoreEvent( event );
+ mCoreEventInterface.ProcessCoreEvents();
+}
+
+void EventHandler::SendEvent( StyleChange::Type styleChange )
+{
+ DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
+ GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
+}
+
+void EventHandler::SendEvent( const DamageArea& area )
+{
+ mDamageObserver.OnDamaged( area );
+}
+
+void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
+{
+ if( mRotationObserver != NULL )
+ {
+ mRotationObserver->OnRotationPrepare( event );
+ }
+}
+
+void EventHandler::SendRotationRequestEvent( )
+{
+ if( mRotationObserver != NULL )
+ {
+ mRotationObserver->OnRotationRequest( );
+ }
+}
+
+void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp)
+{
+ SendEvent(point, timeStamp);
+}
+
+void EventHandler::FeedWheelEvent( WheelEvent& wheelEvent )
+{
+ SendWheelEvent( wheelEvent );
+}
+
+void EventHandler::FeedKeyEvent( KeyEvent& event )
+{
+ SendEvent( event );
+}
+
+void EventHandler::FeedEvent( Integration::Event& event )
+{
+ mCoreEventInterface.QueueCoreEvent( event );
+ mCoreEventInterface.ProcessCoreEvents();
+}
+
+void EventHandler::Reset()
+{
+ mCombiner.Reset();
+
+ // Any touch listeners should be told of the interruption.
+ Integration::TouchEvent event;
+ TouchPoint point(0, TouchPoint::Interrupted, 0, 0);
+ event.AddPoint( point );
+
+ // First the touch event & related gesture events are queued
+ mCoreEventInterface.QueueCoreEvent( event );
+ mGestureManager.SendEvent( event );
+
+ // Next the events are processed with a single call into Core
+ mCoreEventInterface.ProcessCoreEvents();
+}
+
+void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
+{
+ mDragAndDropDetector = detector;
+}
+
+void EventHandler::SetRotationObserver( RotationObserver* observer )
+{
+ mRotationObserver = observer;
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+ // EXTERNAL INCLUDES
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/extensions/XI2.h>
+
+#ifdef DEBUG_ENABLED
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <ostream>
+#include <iomanip>
+#endif
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace X11Debug
+{
+
+#ifdef DEBUG_ENABLED
+
+namespace
+{
+
+
+Integration::Log::Filter* gInputDeviceLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_X_INPUT_DEVICES");
+Integration::Log::Filter* gInputEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_X_INPUT_EVENTS");
+
+struct XNameId
+{
+ const char* const name;
+ int id;
+};
+
+const XNameId eventTable[]=
+{
+ { "XI_KeyPress" ,XI_KeyPress },
+ { "XI_KeyRelease" ,XI_KeyRelease },
+ { "XI_ButtonPress" ,XI_ButtonPress },
+ { "XI_ButtonRelease" ,XI_ButtonRelease },
+ { "XI_Motion" ,XI_Motion },
+ { "XI_Enter" ,XI_Enter },
+ { "XI_Leave" ,XI_Leave },
+ { "XI_FocusIn" ,XI_FocusIn },
+ { "XI_FocusOut" ,XI_FocusOut },
+ { "XI_HierarchyChanged",XI_HierarchyChanged },
+ { "XI_PropertyEvent" ,XI_PropertyEvent },
+ { "XI_RawKeyPress" ,XI_RawKeyPress },
+ { "XI_RawKeyRelease" ,XI_RawKeyRelease },
+ { "XI_RawButtonPress" ,XI_RawButtonPress },
+ { "XI_RawButtonRelease",XI_RawButtonRelease },
+ { "XI_RawMotion" ,XI_RawMotion },
+ { "XI_TouchBegin" ,XI_TouchBegin },
+ { "XI_TouchUpdate" ,XI_TouchUpdate },
+ { "XI_TouchEnd" ,XI_TouchEnd },
+ { "XI_TouchOwnership" ,XI_TouchOwnership },
+ { "XI_RawTouchBegin" ,XI_RawTouchBegin },
+ { "XI_RawTouchUpdate" ,XI_RawTouchUpdate },
+ { "XI_RawTouchEnd" ,XI_RawTouchEnd }
+};
+
+const XNameId deviceTypeTable[]=
+{
+ { "Master Pointer " ,XIMasterPointer },
+ { "Master Keyboard" ,XIMasterKeyboard },
+ { "Slave Pointer " ,XISlavePointer },
+ { "Slave Keyboard " ,XISlaveKeyboard },
+ { "Floating Slave " ,XIFloatingSlave }
+};
+
+const XNameId inputClassTable[]=
+{
+ { "Key" ,XIKeyClass },
+ { "Button" ,XIButtonClass },
+ { "Valuator" ,XIValuatorClass },
+ { "Scroll" ,XIScrollClass },
+ { "Touch" ,XITouchClass }
+};
+
+const unsigned int numberEvents = sizeof( eventTable ) / sizeof( eventTable[0] );
+const unsigned int numberDevices = sizeof( deviceTypeTable ) / sizeof( deviceTypeTable[0] );
+const unsigned int numberInputClasses = sizeof( inputClassTable ) / sizeof( inputClassTable[0] );
+
+const char* GetEventName( int eventId )
+{
+ for( unsigned int i = 0; i < numberEvents; ++i )
+ {
+ if( eventTable[i].id == eventId )
+ {
+ return eventTable[i].name;
+ }
+ }
+ return "unknown event";
+}
+const char* GetDeviceHierachyName( int deviceType )
+{
+ for( unsigned int i = 0; i < numberDevices; ++i )
+ {
+ if( deviceTypeTable[i].id == deviceType )
+ {
+ return deviceTypeTable[i].name;
+ }
+ }
+ return "unknown device";
+}
+const char* GetInputClassName( int classId )
+{
+ for( unsigned int i = 0; i < numberInputClasses; ++i )
+ {
+ if( inputClassTable[i].id == classId )
+ {
+ return inputClassTable[i].name;
+ }
+ }
+ return "unknown input class name";
+}
+
+std::string GetInputDeviceInfo( const XIDeviceInfo* device, bool master )
+{
+ // formatted output similar to xinput -list except it includes class + source information
+ int startWidth = 45;
+
+ std::string slavePadding=" ↳ ";
+ if( master )
+ {
+ // slave entries are shifted to the right
+ startWidth += 4;
+ slavePadding="";
+ }
+
+ std::ostringstream oss;
+ oss << "⎜" << slavePadding << std::setw(startWidth) << std::left << device->name ;
+ oss << std::setw(1) << " id= " << std::setw(1) << device->deviceid ;
+ oss << "\t[" << GetDeviceHierachyName( device->use ) << " ("<< device->attachment << ") ]";
+ oss << std::setw(1) << "\t Classes: ";
+
+ for( int n = 0; n < device->num_classes; ++n )
+ {
+ XIAnyClassInfo *classInfo = device->classes[n];
+ oss << GetInputClassName( classInfo->type ) << ", source ( "<< classInfo->sourceid << ")";
+ }
+ oss << "\n";
+
+ return oss.str();
+}
+
+
+}// unanmed namespace
+
+void LogInputDeviceInfo( const XIDeviceInfo* devices, unsigned int numberOfDevices )
+{
+ // early exit if the filter is not enabled in debug mode
+ if( ! gInputDeviceLogFilter->IsEnabledFor( Debug::General ) )
+ {
+ return;
+ }
+
+ const XIDeviceInfo* device = devices;
+ const XIDeviceInfo* masterKeyboard = NULL;
+ const XIDeviceInfo* masterPointer = NULL;
+ Dali::Vector< const XIDeviceInfo* > slaveKeyboards;
+ Dali::Vector< const XIDeviceInfo* > slavePointers;
+ Dali::Vector< const XIDeviceInfo* > floatingSlaves;
+
+ // go through the device list and sort by type
+ for( unsigned int i = 0; i < numberOfDevices; ++i, ++device )
+ {
+ switch( device->use )
+ {
+ case XIMasterPointer:
+ {
+ masterPointer = device;
+ break;
+ }
+ case XIMasterKeyboard:
+ {
+ masterKeyboard = device;
+ break;
+ }
+ case XISlavePointer:
+ {
+ slavePointers.PushBack( device );
+ break;
+ }
+ case XISlaveKeyboard:
+ {
+ slaveKeyboards.PushBack( device );
+ break;
+ }
+ case XIFloatingSlave:
+ {
+ floatingSlaves.PushBack( device );
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ std::ostringstream oss;
+
+ oss << "\n" << GetInputDeviceInfo( masterKeyboard , true);
+ for( VectorBase::SizeType i = 0; i < slaveKeyboards.Count(); ++i )
+ {
+ oss << GetInputDeviceInfo( slaveKeyboards[i], false );
+ }
+ oss << "\n" << GetInputDeviceInfo( masterPointer, true );
+ for( VectorBase::SizeType i = 0; i < slavePointers.Count(); ++i )
+ {
+ oss << GetInputDeviceInfo( slavePointers[i], false);
+ }
+ for( VectorBase::SizeType i = 0; i < floatingSlaves.Count(); ++i )
+ {
+ oss << GetInputDeviceInfo( floatingSlaves[i], false );
+ }
+
+ // DALI_LOG_ERROR_NOFN( "%s \n",oss.str().c_str() );
+ DALI_LOG_INFO( gInputDeviceLogFilter, Debug::General, "%s\n", oss.str().c_str() );
+}
+
+void LogXI2Event( XGenericEventCookie* cookie )
+{
+ // early exit if the filter is not enabled
+ if( ! gInputEventLogFilter->IsEnabledFor( Debug::General ) )
+ {
+ return;
+ }
+
+ std::ostringstream oss;
+ oss << "XI2 event:" << GetEventName( cookie->evtype );
+
+ XIDeviceEvent *event = static_cast< XIDeviceEvent* >(cookie->data);
+
+ oss << ", device_id("<< event->deviceid << ") source_id( "<< event->sourceid << ")" << ", flags: " << event->flags;
+ oss << ", root-window: " << event->root << ", event-window: "<< event->event << ", child-window:" << event->child;
+ if( cookie->evtype == XI_KeyPress)
+ {
+ oss << "base " << event->mods.base << "latched " << event->mods.latched;
+ oss << "locked " << event->mods.locked << "effective " << event->mods.effective;
+
+ if( event->mods.effective & ShiftMask) oss << "Shift";
+ if( event->mods.effective & LockMask) oss << "LockMask"; // caps lock
+ if( event->mods.effective & ControlMask) oss << "ControlMask";
+ if( event->mods.effective & Mod1Mask) oss << "Mod1Mask"; // alt
+ if( event->mods.effective & Mod2Mask) oss << "Mod2Mask"; // num lock
+ if( event->mods.effective & Mod3Mask) oss << "Mod3Mask";
+ if( event->mods.effective & Mod4Mask) oss << "Mod4Mask"; // WINDOWS
+ if( event->mods.effective & Mod5Mask) oss << "Mod5Mask"; // Alt gr
+
+ }
+
+ // Mouse button state
+ oss << " button state\n";
+ for( int i =0; i< event->buttons.mask_len ; i++)
+ {
+ oss << "," << int(event->buttons.mask[i]);
+ }
+
+ // DALI_LOG_ERROR_NOFN( "%s \n",oss.str().c_str() );
+ DALI_LOG_INFO( gInputEventLogFilter, Debug::General, "%s\n", oss.str().c_str() );
+
+}
+
+
+
+#else
+
+void LogDeviceInfo( Display* display, XIDeviceInfo* device )
+{
+}
+void LogXI2Event( XGenericEventCookie* cookie )
+{
+}
+
+#endif
+
+
+} // X11 Debug
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_INTERNAL_X_INPUT_2_DEBUG_H__
+#define __DALI_INTERNAL_X_INPUT_2_DEBUG_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace X11Debug
+{
+
+/**
+ * To log input devices found on the system buid DALi in debug mode.
+ * Then on the command line:
+ *
+ * export LOG_X_INPUT_DEVICES=2
+ * dali-demo
+ *
+ *
+ * To log XInput events
+ *
+ * export LOG_X_INPUT_EVENTS=2
+ * dali-demo
+ *
+ * 2 = LogLevel::General
+ */
+
+
+/**
+ * @brief Debug log input device information.
+ * Similar output to command line tool 'xinput -list' except it includes class + source information
+ * Useful if the device doesn't have xinput tool installed
+ * @param devices array of XIDeviceInfo
+ * @param numberOfDevices number of devices
+ */
+void LogInputDeviceInfo( const XIDeviceInfo* devices, unsigned int numberOfDevices );
+
+/**
+ * @brief Debug log input event information.
+ * @param cookie input event cookie
+ */
+void LogXI2Event( XGenericEventCookie* cookie );
+
+} // X11 Debug
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
+
+#endif
--- /dev/null
+// CLASS HEADER
+#include "x-event-manager.h"
+
+// EXTERNAL INCLUDES
+#include <stdio.h>
+#include <cstring>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/signals/callback.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+//Dali::Integration::Log::Filter* gInputDeviceLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_X_EVENT");
+#endif
+
+}
+
+XEventManager::XEventManager( XID window, Display* display, WindowEventInterface* eventInterface )
+: mXInput2( window, display, eventInterface ),
+ mFileDescriptorMonitor( NULL ),
+ mDisplay( display ),
+ mWindow( window ),
+ mInitialized( false )
+{
+
+}
+XEventManager::~XEventManager()
+{
+ delete mFileDescriptorMonitor;
+}
+
+void XEventManager::Initialize()
+{
+ if( mInitialized )
+ {
+ return;
+ }
+
+ mXInput2.Initialize();
+
+ // Start monitoring for X events on a file descriptor return via ConnectionNumber.
+ int fileDescriptor = ConnectionNumber( mDisplay );
+
+ CallbackBase* callback = MakeCallback( this, &XEventManager::XEventReceived);
+
+ mFileDescriptorMonitor = new FileDescriptorMonitor( fileDescriptor, callback );
+
+ mInitialized = true;
+}
+
+
+void XEventManager::XEventReceived()
+{
+ while( XPending( mDisplay) )
+ {
+ XEvent xEvent;
+ XNextEvent( mDisplay, &xEvent );
+
+ // cookie data pointer is undefined until XGetEventData is called.
+ XGenericEventCookie* cookie = &xEvent.xcookie;
+
+ if (XGetEventData( mDisplay, cookie))
+ {
+ if( cookie->extension == mXInput2.GetExtensionId() )
+ {
+ mXInput2.ProcessEvent( cookie );
+ }
+ XFreeEventData( mDisplay, cookie );
+ }
+ }
+}
+
+
+} // namespace internal
+} // namespace adaptor
+} // namespace dali
--- /dev/null
+#ifndef __DALI_INTERNAL_X_EVENT_MANAGER_H__
+#define __DALI_INTERNAL_X_EVENT_MANAGER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+// EXTERNAL INCLUDES
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <file-descriptor-monitor.h>
+
+// INTERNAL INCLUDES
+#include <base/interfaces/window-event-interface.h>
+#include "x-input2.h"
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ *
+ * @brief Used to handle X events.
+ * The code is mainloop agnostic, so the monitoring of the X event file descriptor
+ * for X events is external to this class.
+ *
+ */
+class XEventManager
+{
+
+public:
+
+ /**
+ * Constructor
+ * @param[in] window ID
+ * @param[in] display x-connection
+ * @param[in] eventInterface window event interface
+ */
+ XEventManager( XID window, Display* display, WindowEventInterface* eventInterface );
+
+ /**
+ * @brief non virtual destructor
+ */
+ ~XEventManager();
+
+ /**
+ * @brief Initialize
+ */
+ void Initialize();
+
+private:
+
+ /**
+ * @brief Should be called when the Event file descriptor signals data is available
+ */
+ void XEventReceived();
+
+ // Undefined copy constructor.
+ XEventManager( const XEventManager& );
+
+ // Undefined assignment operator.
+ XEventManager& operator=( const XEventManager& );
+
+private:
+
+ XInput2 mXInput2; ///< XInput2 handler
+ FileDescriptorMonitor* mFileDescriptorMonitor; ///< File descriptor monitor for X events
+ Display* mDisplay; ///< X connection
+ XID mWindow; ///< Window to receive events for
+ bool mInitialized:1;
+
+};
+
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_X_EVENT_MANAGER_H__
--- /dev/null
+//CLASS HEADER
+#include "x-input2-device.h"
+
+// EXTERNAL INCLUDES
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+void XInput2Device::AssignDeviceInfo( const XIDeviceInfo* device )
+{
+ deviceId = device->deviceid;
+ attachment = device->attachment;
+ use = device->use;
+
+ for( int n = 0; n < device->num_classes; ++n )
+ {
+ XIAnyClassInfo *classInfo = device->classes[n];
+ switch( classInfo->type )
+ {
+ case XITouchClass:
+ {
+ touchClass = true;
+ break;
+ }
+ case XIButtonClass:
+ {
+ buttonClass = true;
+ break;
+ }
+ case XIValuatorClass:
+ {
+ valuatorClass = true;
+ break;
+ }
+ case XIScrollClass:
+ {
+ scrollClass = true;
+ break;
+ }
+ case XIKeyClass:
+ {
+ keyClass = true;
+ break;
+ }
+ default:
+ {
+ // unknown
+ break;
+ }
+ }
+ }
+
+
+}
+
+
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_INTERNAL_X_INPUT2_DEVICE_H__
+#define __DALI_INTERNAL_X_INPUT2_DEVICE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <X11/extensions/XInput2.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+
+/**
+ * @brief struct used to encpasulate XIDeviceInfo information.
+ * Kept as a POD so it can be used in a Dali::Vector
+ */
+struct XInput2Device
+{
+ /**
+ * @brief constructor
+ */
+ XInput2Device()
+ : deviceId(0),
+ attachment(0),
+ use(0),
+ keyClass(false),
+ touchClass(false),
+ buttonClass(false),
+ valuatorClass(false),
+ scrollClass(false)
+ {}
+
+ /**
+ * Assign device information to the object
+ */
+ void AssignDeviceInfo( const XIDeviceInfo* device );
+
+ int deviceId; ///< X device ID
+ int attachment; ///< see XI2 DEVICEINFO struct for details
+ int use; ///< see XI2 DEVICEINFO struct for details
+ bool keyClass:1; ///< device supports key input
+ bool touchClass:1; ///< device supports touch input
+ bool buttonClass:1; ///< device supports button input
+ bool valuatorClass:1; ///< device supports an axis, e.g. mouse axis, tablet pen tilt angle..
+ bool scrollClass:1; ///< device supports scroll
+
+};
+
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
+
+#endif
--- /dev/null
+// CLASS HEADER
+#include "x-input2.h"
+
+// EXTERNAL INCLUDES
+#include <X11/XKBlib.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include "debug/x-input2-debug.h"
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+// For multi-touch we need XI2 version 2.2
+int XI2MinorVersionRequired = 2;
+int XI2MajorVersionRequired = 2;
+}
+
+XInput2::XInput2( XID window, Display* display, WindowEventInterface* eventInterface )
+: mEventInterface( eventInterface ),
+ mDisplay( display ),
+ mWindow( window ),
+ mXI2ExtensionId(-1),
+ mMultiTouchSupport( false )
+{
+
+}
+XInput2::~XInput2()
+{
+}
+
+void XInput2::Initialize()
+{
+ // Check if X supports the multi-touch protocol
+ QueryMultiTouchSupport();
+
+ // Query what input devices are available on the system.
+ QueryDevices();
+
+ // Select the input events we want to receive from the input devices available
+ SelectInputEvents();
+
+}
+
+int XInput2::GetExtensionId() const
+{
+ return mXI2ExtensionId;
+}
+
+bool XInput2::FilteredDevice( int deviceId ) const
+{
+ for( VectorBase::SizeType i = 0; i < mInputDeviceInfo.Count(); ++i )
+ {
+ if( mInputDeviceInfo[i].deviceId == deviceId )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool XInput2::PreProcessEvent( XIDeviceEvent *deviceEvent ) const
+{
+ // @todo need to do some testing to see if this check is actually required
+ // E.g. if IME window is sending events, this check may fail
+ if( deviceEvent->event != mWindow )
+ {
+ return false;
+ }
+ // emulated flags means that the event has been emulated from another XI 2.x event for legacy client support
+ // We don't call XISelectEvents on these events so hopefully shouldn't get them.
+ if( ( deviceEvent->flags & XIPointerEmulated ) || ( deviceEvent->flags & XITouchEmulatingPointer ) )
+ {
+ return false;
+ }
+
+ if( !FilteredDevice( deviceEvent->deviceid ))
+ {
+ return false;
+ }
+ return true;
+}
+
+void XInput2::CreateKeyEvent( const XIDeviceEvent* deviceEvent, KeyEvent& keyEvent ) const
+{
+ // get the physical key code ( range 8..255)
+ KeyCode keycode = deviceEvent->detail;
+
+ keyEvent.keyCode = keycode;
+ keyEvent.state = KeyEvent::Down;
+ keyEvent.keyModifier = deviceEvent->mods.effective;
+
+ // extract key symbol. The symbol is typically the name visible on the key
+ // e.g. key code 201 might = Brightness increase, or a Korean character depending on the keyboard mapping.
+ // @todo For XKbKeycodeToKeysym to work correctly we need the group and level.
+ // investigate using XkbGetState to get initial state then start monitoring for XkbStateNotify events
+ KeySym sym = XkbKeycodeToKeysym( mDisplay, keycode, 0 /* group */ , keyEvent.IsShiftModifier() );
+ char* keyname = XKeysymToString( sym );
+
+ keyEvent.keyPressedName = keyname;
+ keyEvent.time = deviceEvent->time;
+
+}
+
+void XInput2::ProcessEvent( XGenericEventCookie* cookie )
+{
+ XIDeviceEvent* deviceEvent = static_cast< XIDeviceEvent* >(cookie->data);
+
+ X11Debug::LogXI2Event( cookie );
+
+ bool requiresProcessing = PreProcessEvent( deviceEvent );
+
+ if( ! requiresProcessing )
+ {
+ return;
+ }
+
+ TouchPoint point ( deviceEvent->deviceid, TouchPoint::Last, deviceEvent->event_x, deviceEvent->event_y );
+ Time time( deviceEvent->time ); // X is using uint32 for time field ( see XI2proto.h )
+
+ switch( cookie->evtype)
+ {
+ case XI_TouchUpdate:
+ case XI_Motion:
+ {
+ point.state = TouchPoint::Motion;
+ mEventInterface->TouchEvent( point, time );
+ break;
+ }
+ case XI_TouchBegin:
+ case XI_ButtonPress:
+ {
+ point.state = TouchPoint::Down;
+ mEventInterface->TouchEvent( point, time );
+ break;
+ }
+ case XI_TouchEnd:
+ case XI_ButtonRelease:
+ {
+ point.state = TouchPoint::Up;
+ mEventInterface->TouchEvent( point, time );
+ break;
+ }
+ case XI_FocusIn:
+ {
+ mEventInterface->WindowFocusIn();
+ break;
+ }
+ case XI_FocusOut:
+ {
+ mEventInterface->WindowFocusOut();
+ break;
+ }
+ case XI_KeyPress:
+ {
+ KeyEvent keyEvent;
+ CreateKeyEvent( deviceEvent, keyEvent );
+ mEventInterface->KeyEvent( keyEvent );
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void XInput2::QueryMultiTouchSupport()
+{
+ int minor = XI2MinorVersionRequired;
+ int major = XI2MajorVersionRequired;
+ int firstEventCode, firstErrorCode;
+
+ // Check if the extension is available and get the extension id
+ if( !XQueryExtension(mDisplay, "XInputExtension", &mXI2ExtensionId, &firstEventCode, &firstErrorCode) )
+ {
+ DALI_LOG_ERROR(" XInputExtension not available \n");
+ return;
+ }
+
+ // inform X that DALi ( the client ) supports XI2 version 2.2
+ // it will assign the X servers supported version to the parameters
+ int ret = XIQueryVersion( mDisplay, &major, &minor);
+ if( ret == BadValue )
+ {
+ DALI_LOG_ERROR(" XIQueryVersion %d,%d failed \n", major, minor );
+ return;
+ }
+
+ // check the version is supports multi-touch
+ if( ( major * 1000 + minor ) >= ( XI2MajorVersionRequired * 1000 + XI2MinorVersionRequired ) )
+ {
+ mMultiTouchSupport = true;
+ }
+ else
+ {
+ DALI_LOG_ERROR( "XInput 2.2 or greater required for multi-touch\n");
+ }
+
+}
+void XInput2::QueryDevices()
+ {
+ int numberOfDevices( 0 );
+
+ // QueryDevice returns information about one or more input devices
+ XIDeviceInfo* deviceInfoArray = XIQueryDevice( mDisplay, XIAllDevices, &numberOfDevices);
+ XIDeviceInfo* device = deviceInfoArray;
+
+ X11Debug::LogInputDeviceInfo( deviceInfoArray, numberOfDevices );
+
+ mInputDeviceInfo.Resize( numberOfDevices );
+
+ for( int i = 0; i < numberOfDevices; ++i, ++device )
+ {
+ XInput2Device info;
+
+ info.AssignDeviceInfo( device );
+
+ mInputDeviceInfo.PushBack( info );
+ }
+
+ XIFreeDeviceInfo( deviceInfoArray );
+ }
+
+void XInput2::SelectEvents( int deviceId, const Dali::Vector< unsigned int >& filter )
+{
+ if( filter.Size() == 0)
+ {
+ return;
+ }
+
+ // each event like XI_ButtonPress is stored as unique bit, so if there's 32 events we need 4 bytes
+ // the XIMaskLen macro provides the length for us at compile time.
+ unsigned char mask[ XIMaskLen( XI_LASTEVENT ) ] = {};
+ XIEventMask eventMask;
+
+ eventMask.deviceid = deviceId;
+ eventMask.mask_len = sizeof( mask);
+ eventMask.mask = mask;
+
+ for( VectorBase::SizeType i = 0; i< filter.Count(); ++i )
+ {
+ XISetMask( mask, filter[i] );
+ }
+
+ XISelectEvents( mDisplay, mWindow, &eventMask, 1);
+
+}
+void XInput2::SelectInputEvents()
+{
+ /*
+ * From the X documentation:
+ * "A master pointer is a virtual pointer device that does not represent a physical device.
+ * If a slave device generates an event, the event is also generated by the respective master device.
+ * Multiple slave devices can be attached to a single master device."
+ * master = cursor / keyboard focus,
+ * slave = physical device
+ *
+ * For motion events, we currently just listen to the slave devices. This allows us the ability to
+ * perform a XIGrabDevice on the slave if we need to, which will temporarily detach it from the master.
+ * In DALi we currently don't perform a grab as typically we just have a single x-window displayed.
+ * Where as other toolkits may have a window for a popup and want do know when the mouse is clicked outside
+ * of the popup, to close it.
+ */
+ Dali::Vector< unsigned int > eventFilter;
+ eventFilter.Reserve( 6 ); // typically filter no more than 6 events
+
+ for( VectorBase::SizeType i = 0; i < mInputDeviceInfo.Count(); ++i )
+ {
+ const XInput2Device& device( mInputDeviceInfo[ i ] );
+
+ eventFilter.Clear();
+
+ if( ( device.use == XIFloatingSlave ) || ( device.use == XISlavePointer ))
+ {
+ if( device.buttonClass )
+ {
+ eventFilter.PushBack( XI_ButtonPress );
+ eventFilter.PushBack( XI_ButtonRelease );
+ eventFilter.PushBack( XI_Motion );
+ }
+ if( device.touchClass )
+ {
+ eventFilter.PushBack( XI_TouchUpdate );
+ eventFilter.PushBack( XI_TouchBegin );
+ eventFilter.PushBack( XI_TouchEnd );
+ }
+ SelectEvents( device.deviceId, eventFilter );
+ }
+ // @todo work out if we should just be listening to MasterKeyboard
+ else if( device.use == XISlaveKeyboard )
+ {
+ if( device.keyClass )
+ {
+ eventFilter.PushBack( XI_KeyPress );
+ eventFilter.PushBack( XI_KeyRelease );
+
+ SelectEvents( device.deviceId, eventFilter );
+ }
+
+ }
+ }
+}
+} // namespace internal
+} // namespace adaptor
+} // namespace dali
--- /dev/null
+#ifndef __DALI_INTERNAL_X_INPUT_2_MANAGER_H__
+#define __DALI_INTERNAL_X_INPUT_2_MANAGER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/extensions/XI2.h>
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <base/interfaces/window-event-interface.h>
+#include "x-input2-device.h"
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ *
+ * @brief Used to setup and process XInput2 events.
+ *
+ * For help with debugging, build DALi in debug mode then set the environment variables
+ * export LOG_X_INPUT_EVENTS=2
+ * export LOG_X_INPUT_DEVICES=2
+ */
+class XInput2
+{
+
+public:
+
+ /**
+ * @brief Constructor
+ */
+ XInput2( XID window, Display* display, WindowEventInterface* eventInterface );
+
+ /**
+ * @brief destructor
+ */
+ ~XInput2();
+
+ /**
+ * @brief enumerates input devices using XIQueryDevice then sets up event filtering using XISelectEvents
+ */
+ void Initialize();
+
+ /**
+ * @brief get X the extension id
+ * @return the Id
+ */
+ int GetExtensionId() const;
+
+ /**
+ * @brief process an XInput2 event
+ * @param cookie X cookie
+ */
+ void ProcessEvent( XGenericEventCookie* cookie );
+
+
+private:
+
+ /**
+ * @brief query x input devices
+ */
+ void QueryDevices();
+
+ /**
+ * @brief query multi-touch support
+ */
+ void QueryMultiTouchSupport();
+
+ /**
+ * Uses XISelectEvents to select the events we want to recieve from each input device
+ */
+ void SelectInputEvents();
+
+ /**
+ * @brief checks if we are filtering events from a specific device
+ * @param[in] deviceId device id
+ * @return true if the device is being filtered
+ */
+ bool FilteredDevice( int deviceId ) const;
+
+ /**
+ * @brief Select specific events to be filtered on a device
+ * @param[in] device id
+ * @param[in] filter vector of X input events like XI_ButtonPress
+ */
+ void SelectEvents( int deviceId, const Dali::Vector< unsigned int >& filter );
+
+ /**
+ * @brief checks if the event should be processed
+ * @param[in] deviceEvent device event
+ * @return true if should be processed
+ */
+ bool PreProcessEvent( XIDeviceEvent *deviceEvent ) const;
+
+ /**
+ * @brief creates a DALi key event given a XIDeviceEvent for a key press
+ * @param[in] deviceEvent device event
+ * @param[out] keyEvent DALi key event
+ */
+ void CreateKeyEvent( const XIDeviceEvent* deviceEvent, KeyEvent& keyEvent ) const;
+
+private:
+
+ Dali::Vector< XInput2Device > mInputDeviceInfo; ///< list of input devices
+ WindowEventInterface* mEventInterface; ///< window event interface
+ Display* mDisplay; ///< X display
+ XID mWindow; ///< X window
+ int mXI2ExtensionId; ///< XI2 extension id
+ bool mMultiTouchSupport:1; ///< whether multi-touch is supported
+};
+
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
+
+#endif
endif
+# Node JS support for using an external libuv main loop. If not enabled then just use e-core as normal
+# Used for things like callbacks, file-monintors, x input handling
+if LIB_UV_EVENT_LOOP
+main_loop_integration_src_files = $(adaptor_common_internal_uv_src_files)
+input_event_handler_src_files = $(adaptor_uv_x_event_handler_internal_src_files)
+else
+main_loop_integration_src_files = $(adaptor_common_internal_ecore_src_files)
+input_event_handler_src_files = $(adaptor_ecore_x_event_handler_internal_src_files)
+endif
+
+
+
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = dali-adaptor-integration.pc
libdali_adaptor_la_SOURCES = \
$(base_adaptor_src_files) \
+ $(main_loop_integration_src_files) \
$(tizen_platform_abstraction_src_files) \
$(text_abstraction_src_files) \
$(devel_api_src_files) \
$(public_api_src_files) \
- $(adaptor_internal_src_files)
+ $(adaptor_internal_src_files) \
+ $(input_event_handler_src_files)
+
libdali_adaptor_la_DEPENDENCIES =
# linking test
+# turn off the linker test if were building for libuv
+# We can't link to LibUV becase it is statically linked to Node.JS (by default)
+if !LIB_UV_EVENT_LOOP
noinst_PROGRAMS = linker.test
+endif # NOT LIB_UV_EVENT_LOOP
linker_test_SOURCES = linker-test.cpp
linker_test_CXXFLAGS = \
+ -DDALI_ADAPTOR_COMPILATION \
-I../../../adaptors/common \
-I../../../adaptors/public-api \
- -I../../../adaptors/integration-api \
+ -I../../../adaptors/integration-api \
-I../../../adaptors/base/interfaces \
-I../../../adaptors/public-api/adaptor-framework \
-I../../../adaptors/devel-api/adaptor-framework \
DALI_ADAPTOR_CFLAGS="$DALI_ADAPTOR_CFLAGS -DDALI_GLES_VERSION=${enable_gles}"
+# node.js by default statically links against libuv, so it doesn't need to install
+# a libuv headers/ shared library. So we can't use pkg-config to access any headers.
+# As a work around we pass the node deps path so we can access the libuv headers inside nodes
+# directory
+AC_ARG_WITH([node-js],
+ [AC_HELP_STRING([--with-node-js],
+ [Node.JS path that contains Lib UV headers. Setting this configures DALi to work with LibUV mainloop used in Node.JS.
+ For example /usr/tmp/downloads/node-v0.12.4/deps/uv/include/ ])],
+ [with_node_js=$withval],
+ [with_node_js=no])
+
+# Node.JS already has a libuv main loop running,so we have to integrate with it
+AM_CONDITIONAL(LIB_UV_EVENT_LOOP, test x$with_node_js != xno)
+
+
+build_for_node_js=no
+if test "x$with_node_js" != "xno"; then
+ AC_MSG_NOTICE("build for node_js == yes");
+ [build_for_node_js=yes]
+ DALI_ADAPTOR_CFLAGS="$DALI_ADAPTOR_CFLAGS -DNODE_JS_SUPPORT -I${with_node_js}"
+else
+ #not using node.js build
+ AC_MSG_NOTICE("build for node_js == no");
+fi
+
+
AC_ARG_WITH([over-tizen_2_2],
[AC_HELP_STRING([--with-over-tizen_2_2],
[Use tizen API over ver. 2.2])],
Data Dir (Read Only): $dataReadOnlyDir
OVERTIZEN2.2: $with_over_tizen_2_2
EldBus: $eldbus_available
+ Build for Node.JS (LibUV) $build_for_node_js
"
+# optional output of node.js source path if we're building for node.js
+if test "x$build_for_node_js" != "xno"; then
+echo " Node.JS LibUV header path $with_node_js"
+fi