b801cb2b275243e615aa353a601effbd375fc2ed
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / x-event-handler.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <events/event-handler.h>
20
21 // EXTERNAL INCLUDES
22 #include <uv.h>
23 #include <Ecore_X.h>
24
25 #include <X11/Xlib.h>
26 #include <X11/extensions/XInput2.h>
27 #include <X11/extensions/XI2.h>
28
29 #include <cstring>
30
31 #include <sys/time.h>
32
33 #ifndef DALI_PROFILE_UBUNTU
34 #include <vconf.h>
35 #include <vconf-keys.h>
36 #endif // DALI_PROFILE_UBUNTU
37
38 #include <dali/public-api/common/vector-wrapper.h>
39 #include <dali/public-api/events/touch-point.h>
40 #include <dali/public-api/events/key-event.h>
41 #include <dali/public-api/events/wheel-event.h>
42 #include <dali/integration-api/debug.h>
43 #include <dali/integration-api/events/key-event-integ.h>
44 #include <dali/integration-api/events/touch-event-integ.h>
45 #include <dali/integration-api/events/hover-event-integ.h>
46 #include <dali/integration-api/events/wheel-event-integ.h>
47
48 // INTERNAL INCLUDES
49 #include <x-events/x-event-manager.h>
50 #include <events/gesture-manager.h>
51 #include <window-render-surface.h>
52 #include <clipboard-impl.h>
53 #include <key-impl.h>
54 #include <physical-keyboard-impl.h>
55 #include <style-monitor-impl.h>
56 #include <base/core-event-interface.h>
57 #include <base/interfaces/window-event-interface.h>
58
59 namespace Dali
60 {
61
62 namespace Internal
63 {
64
65 namespace Adaptor
66 {
67
68 #if defined(DEBUG_ENABLED)
69 namespace
70 {
71 Integration::Log::Filter* gTouchEventLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH");
72 } // unnamed namespace
73 #endif
74
75
76 namespace
77 {
78
79 const unsigned int PRIMARY_TOUCH_BUTTON_ID( 1 );
80
81 const unsigned int BYTES_PER_CHARACTER_FOR_ATTRIBUTES = 3;
82
83
84 // Copied from x server
85 static unsigned int GetCurrentMilliSeconds(void)
86 {
87   struct timeval tv;
88
89   struct timespec tp;
90   static clockid_t clockid;
91
92   if (!clockid)
93   {
94 #ifdef CLOCK_MONOTONIC_COARSE
95     if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
96       (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
97     {
98       clockid = CLOCK_MONOTONIC_COARSE;
99     }
100     else
101 #endif
102     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
103     {
104       clockid = CLOCK_MONOTONIC;
105     }
106     else
107     {
108       clockid = ~0L;
109     }
110   }
111   if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
112   {
113     return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
114   }
115
116   gettimeofday(&tv, NULL);
117   return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
118 }
119
120 } // unnamed namespace
121
122
123 struct EventHandler::Impl : public WindowEventInterface
124 {
125   // Construction & Destruction
126
127   /**
128    * Constructor
129    */
130   Impl( EventHandler* handler, XID window, Display* display )
131   : mXEventManager(window, display, this),
132     mHandler( handler )
133   {
134     mXEventManager.Initialize();
135   }
136   /**
137    * Destructor
138    */
139   ~Impl()
140   {
141   }
142   // @todo Consider allowing the EventHandler class to inherit from WindowEventInterface directly
143   virtual void TouchEvent( Dali::TouchPoint& point, unsigned long timeStamp )
144   {
145     mHandler->SendEvent( point, timeStamp );
146   }
147   virtual void KeyEvent( Dali::KeyEvent& keyEvent )
148   {
149     mHandler->SendEvent( keyEvent );
150   }
151   virtual void WheelEvent( Dali::WheelEvent& wheelEvent )
152   {
153     mHandler->SendWheelEvent( wheelEvent );
154   }
155   virtual void DamageEvent( Rect<int>& damageArea )
156   {
157     mHandler->SendEvent( damageArea );
158   }
159   virtual void WindowFocusOut( )
160   {
161     // used to do some work with ime
162   }
163   virtual void WindowFocusIn()
164   {
165     // used to do some work with ime
166   }
167
168   // Data
169   XEventManager mXEventManager;
170   EventHandler* mHandler;
171 };
172
173 EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector )
174 : mCoreEventInterface(coreEventInterface),
175   mGestureManager( gestureManager ),
176   mStyleMonitor( StyleMonitor::Get() ),
177   mDamageObserver( damageObserver ),
178   mRotationObserver( NULL ),
179   mDragAndDropDetector( dndDetector ),
180   mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
181   mClipboard(Clipboard::Get()),
182   mImpl( NULL )
183 {
184   Ecore_X_Window window = 0;
185
186   // this code only works with the EcoreX11 RenderSurface so need to downcast
187   ECore::WindowRenderSurface* ecoreSurface = dynamic_cast< ECore::WindowRenderSurface* >( surface );
188   if( ecoreSurface )
189   {
190     window = ecoreSurface->GetXWindow();
191     Display* display = static_cast< Display* >(ecore_x_display_get());
192
193     mImpl = new Impl(this, window, display );
194
195   }
196
197 }
198
199 EventHandler::~EventHandler()
200 {
201   if(mImpl)
202   {
203     delete mImpl;
204   }
205
206   mGestureManager.Stop();
207 }
208
209 void EventHandler::SendEvent(TouchPoint& point, unsigned long timeStamp)
210 {
211   if(timeStamp < 1)
212   {
213     timeStamp = GetCurrentMilliSeconds();
214   }
215
216   Integration::TouchEvent touchEvent;
217   Integration::HoverEvent hoverEvent;
218   Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
219   if(type != Integration::TouchEventCombiner::DispatchNone )
220   {
221     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);
222
223     // First the touch and/or hover event & related gesture events are queued
224     if(type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth)
225     {
226       mCoreEventInterface.QueueCoreEvent( touchEvent );
227       mGestureManager.SendEvent(touchEvent);
228     }
229
230     if(type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth)
231     {
232       mCoreEventInterface.QueueCoreEvent( hoverEvent );
233     }
234
235     // Next the events are processed with a single call into Core
236     mCoreEventInterface.ProcessCoreEvents();
237   }
238 }
239
240 void EventHandler::SendEvent(KeyEvent& keyEvent)
241 {
242   Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
243   if ( physicalKeyboard )
244   {
245     if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ) )
246     {
247       GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
248     }
249   }
250
251   // Create KeyEvent and send to Core.
252   Integration::KeyEvent event(keyEvent.keyPressedName, keyEvent.keyPressed, keyEvent.keyCode,
253   keyEvent.keyModifier, keyEvent.time, static_cast<Integration::KeyEvent::State>(keyEvent.state));
254   mCoreEventInterface.QueueCoreEvent( event );
255   mCoreEventInterface.ProcessCoreEvents();
256 }
257
258 void EventHandler::SendWheelEvent( WheelEvent& wheelEvent )
259 {
260   // Create WheelEvent and send to Core.
261   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
262   mCoreEventInterface.QueueCoreEvent( event );
263   mCoreEventInterface.ProcessCoreEvents();
264 }
265
266 void EventHandler::SendEvent( StyleChange::Type styleChange )
267 {
268   DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
269   GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
270 }
271
272 void EventHandler::SendEvent( const DamageArea& area )
273 {
274   mDamageObserver.OnDamaged( area );
275 }
276
277 void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
278 {
279   if( mRotationObserver != NULL )
280   {
281     mRotationObserver->OnRotationPrepare( event );
282   }
283 }
284
285 void EventHandler::SendRotationRequestEvent( )
286 {
287   if( mRotationObserver != NULL )
288   {
289     mRotationObserver->OnRotationRequest( );
290   }
291 }
292
293 void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp)
294 {
295   SendEvent(point, timeStamp);
296 }
297
298 void EventHandler::FeedWheelEvent( WheelEvent& wheelEvent )
299 {
300   SendWheelEvent( wheelEvent );
301 }
302
303 void EventHandler::FeedKeyEvent( KeyEvent& event )
304 {
305   SendEvent( event );
306 }
307
308 void EventHandler::FeedEvent( Integration::Event& event )
309 {
310   mCoreEventInterface.QueueCoreEvent( event );
311   mCoreEventInterface.ProcessCoreEvents();
312 }
313
314 void EventHandler::Reset()
315 {
316   mCombiner.Reset();
317
318   // Any touch listeners should be told of the interruption.
319   Integration::TouchEvent event;
320   TouchPoint point(0, TouchPoint::Interrupted, 0, 0);
321   event.AddPoint( point );
322
323   // First the touch event & related gesture events are queued
324   mCoreEventInterface.QueueCoreEvent( event );
325   mGestureManager.SendEvent( event );
326
327   // Next the events are processed with a single call into Core
328   mCoreEventInterface.ProcessCoreEvents();
329 }
330
331 void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
332 {
333   mDragAndDropDetector = detector;
334 }
335
336 void EventHandler::SetRotationObserver( RotationObserver* observer )
337 {
338   mRotationObserver = observer;
339 }
340
341 } // namespace Adaptor
342
343 } // namespace Internal
344
345 } // namespace Dali