b8cb525f2d1f716601c8ea02e168da28845650fa
[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     mPaused( false )
134   {
135     mXEventManager.Initialize();
136   }
137   /**
138    * Destructor
139    */
140   ~Impl()
141   {
142   }
143   // @todo Consider allowing the EventHandler class to inherit from WindowEventInterface directly
144   virtual void TouchEvent( Dali::TouchPoint& point, unsigned long timeStamp )
145   {
146     mHandler->SendEvent( point, timeStamp );
147   }
148   virtual void KeyEvent( Dali::KeyEvent& keyEvent )
149   {
150     mHandler->SendEvent( keyEvent );
151   }
152   virtual void WheelEvent( Dali::WheelEvent& wheelEvent )
153   {
154     mHandler->SendWheelEvent( wheelEvent );
155   }
156   virtual void DamageEvent( Rect<int>& damageArea )
157   {
158     mHandler->SendEvent( damageArea );
159   }
160   virtual void WindowFocusOut( )
161   {
162     // used to do some work with ime
163   }
164   virtual void WindowFocusIn()
165   {
166     // used to do some work with ime
167   }
168
169   // Data
170   XEventManager mXEventManager;
171   EventHandler* mHandler;
172 };
173
174 EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector )
175 : mCoreEventInterface(coreEventInterface),
176   mGestureManager( gestureManager ),
177   mStyleMonitor( StyleMonitor::Get() ),
178   mDamageObserver( damageObserver ),
179   mRotationObserver( NULL ),
180   mDragAndDropDetector( dndDetector ),
181   mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
182   mClipboard(Clipboard::Get()),
183   mImpl( NULL )
184 {
185   Ecore_X_Window window = 0;
186
187   // this code only works with the EcoreX11 RenderSurface so need to downcast
188   ECore::WindowRenderSurface* ecoreSurface = dynamic_cast< ECore::WindowRenderSurface* >( surface );
189   if( ecoreSurface )
190   {
191     window = ecoreSurface->GetXWindow();
192     Display* display = static_cast< Display* >(ecore_x_display_get());
193
194     mImpl = new Impl(this, window, display );
195
196   }
197
198 }
199
200 EventHandler::~EventHandler()
201 {
202   if(mImpl)
203   {
204     delete mImpl;
205   }
206
207   mGestureManager.Stop();
208 }
209
210 void EventHandler::SendEvent(TouchPoint& point, unsigned long timeStamp)
211 {
212   if(timeStamp < 1)
213   {
214     timeStamp = GetCurrentMilliSeconds();
215   }
216
217   Integration::TouchEvent touchEvent;
218   Integration::HoverEvent hoverEvent;
219   Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
220   if(type != Integration::TouchEventCombiner::DispatchNone )
221   {
222     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);
223
224     // First the touch and/or hover event & related gesture events are queued
225     if(type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth)
226     {
227       mCoreEventInterface.QueueCoreEvent( touchEvent );
228       mGestureManager.SendEvent(touchEvent);
229     }
230
231     if(type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth)
232     {
233       mCoreEventInterface.QueueCoreEvent( hoverEvent );
234     }
235
236     // Next the events are processed with a single call into Core
237     mCoreEventInterface.ProcessCoreEvents();
238   }
239 }
240
241 void EventHandler::SendEvent(KeyEvent& keyEvent)
242 {
243   Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
244   if ( physicalKeyboard )
245   {
246     if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ) )
247     {
248       GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
249     }
250   }
251
252   // Create KeyEvent and send to Core.
253   Integration::KeyEvent event(keyEvent.keyPressedName, keyEvent.keyPressed, keyEvent.keyCode,
254   keyEvent.keyModifier, keyEvent.time, static_cast<Integration::KeyEvent::State>(keyEvent.state));
255   mCoreEventInterface.QueueCoreEvent( event );
256   mCoreEventInterface.ProcessCoreEvents();
257 }
258
259 void EventHandler::SendWheelEvent( WheelEvent& wheelEvent )
260 {
261   // Create WheelEvent and send to Core.
262   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
263   mCoreEventInterface.QueueCoreEvent( event );
264   mCoreEventInterface.ProcessCoreEvents();
265 }
266
267 void EventHandler::SendEvent( StyleChange::Type styleChange )
268 {
269   DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
270   GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
271 }
272
273 void EventHandler::SendEvent( const DamageArea& area )
274 {
275   mDamageObserver.OnDamaged( area );
276 }
277
278 void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
279 {
280   if( mRotationObserver != NULL )
281   {
282     mRotationObserver->OnRotationPrepare( event );
283   }
284 }
285
286 void EventHandler::SendRotationRequestEvent( )
287 {
288   if( mRotationObserver != NULL )
289   {
290     mRotationObserver->OnRotationRequest( );
291   }
292 }
293
294 void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp)
295 {
296   SendEvent(point, timeStamp);
297 }
298
299 void EventHandler::FeedWheelEvent( WheelEvent& wheelEvent )
300 {
301   SendWheelEvent( wheelEvent );
302 }
303
304 void EventHandler::FeedKeyEvent( KeyEvent& event )
305 {
306   SendEvent( event );
307 }
308
309 void EventHandler::FeedEvent( Integration::Event& event )
310 {
311   mCoreEventInterface.QueueCoreEvent( event );
312   mCoreEventInterface.ProcessCoreEvents();
313 }
314
315 void EventHandler::Reset()
316 {
317   mCombiner.Reset();
318
319   // Any touch listeners should be told of the interruption.
320   Integration::TouchEvent event;
321   TouchPoint point(0, TouchPoint::Interrupted, 0, 0);
322   event.AddPoint( point );
323
324   // First the touch event & related gesture events are queued
325   mCoreEventInterface.QueueCoreEvent( event );
326   mGestureManager.SendEvent( event );
327
328   // Next the events are processed with a single call into Core
329   mCoreEventInterface.ProcessCoreEvents();
330 }
331
332 void EventHandler::Pause()
333 {
334   mPaused = true;
335   Reset();
336 }
337
338 void EventHandler::Resume()
339 {
340   mPaused = false;
341   Reset();
342 }
343
344 void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
345 {
346   mDragAndDropDetector = detector;
347 }
348
349 void EventHandler::SetRotationObserver( RotationObserver* observer )
350 {
351   mRotationObserver = observer;
352 }
353
354 } // namespace Adaptor
355
356 } // namespace Internal
357
358 } // namespace Dali