0e73249f80c476171551aba35a3e1dfaa17e2da2
[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::Integration::Point& 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   bool mPaused;
173 };
174
175 EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector )
176 : mCoreEventInterface(coreEventInterface),
177   mGestureManager( gestureManager ),
178   mStyleMonitor( StyleMonitor::Get() ),
179   mDamageObserver( damageObserver ),
180   mRotationObserver( NULL ),
181   mDragAndDropDetector( dndDetector ),
182   mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
183   mClipboard(Clipboard::Get()),
184   mImpl( NULL )
185 {
186   Ecore_X_Window window = 0;
187
188   // this code only works with the EcoreX11 RenderSurface so need to downcast
189   ECore::WindowRenderSurface* ecoreSurface = dynamic_cast< ECore::WindowRenderSurface* >( surface );
190   if( ecoreSurface )
191   {
192     window = ecoreSurface->GetXWindow();
193     Display* display = static_cast< Display* >(ecore_x_display_get());
194
195     mImpl = new Impl(this, window, display );
196
197   }
198
199 }
200
201 EventHandler::~EventHandler()
202 {
203   if(mImpl)
204   {
205     delete mImpl;
206   }
207
208   mGestureManager.Stop();
209 }
210
211 void EventHandler::SendEvent(Dali::Integration::Point& point, unsigned long timeStamp)
212 {
213   if(timeStamp < 1)
214   {
215     timeStamp = GetCurrentMilliSeconds();
216   }
217
218   Integration::TouchEvent touchEvent;
219   Integration::HoverEvent hoverEvent;
220   Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
221   if(type != Integration::TouchEventCombiner::DispatchNone )
222   {
223     DALI_LOG_INFO(gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetLocalPosition().x, point.GetLocalPosition().y);
224
225     // First the touch and/or hover event & related gesture events are queued
226     if(type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth)
227     {
228       mCoreEventInterface.QueueCoreEvent( touchEvent );
229       mGestureManager.SendEvent(touchEvent);
230     }
231
232     if(type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth)
233     {
234       mCoreEventInterface.QueueCoreEvent( hoverEvent );
235     }
236
237     // Next the events are processed with a single call into Core
238     mCoreEventInterface.ProcessCoreEvents();
239   }
240 }
241
242 void EventHandler::SendEvent(KeyEvent& keyEvent)
243 {
244   Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
245   if ( physicalKeyboard )
246   {
247     if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ) )
248     {
249       GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
250     }
251   }
252
253   // Create KeyEvent and send to Core.
254   Integration::KeyEvent event(keyEvent.keyPressedName, keyEvent.keyPressed, keyEvent.keyCode,
255   keyEvent.keyModifier, keyEvent.time, static_cast<Integration::KeyEvent::State>(keyEvent.state));
256   mCoreEventInterface.QueueCoreEvent( event );
257   mCoreEventInterface.ProcessCoreEvents();
258 }
259
260 void EventHandler::SendWheelEvent( WheelEvent& wheelEvent )
261 {
262   // Create WheelEvent and send to Core.
263   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
264   mCoreEventInterface.QueueCoreEvent( event );
265   mCoreEventInterface.ProcessCoreEvents();
266 }
267
268 void EventHandler::SendEvent( StyleChange::Type styleChange )
269 {
270   DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
271   GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
272 }
273
274 void EventHandler::SendEvent( const DamageArea& area )
275 {
276   mDamageObserver.OnDamaged( area );
277 }
278
279 void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
280 {
281   if( mRotationObserver != NULL )
282   {
283     mRotationObserver->OnRotationPrepare( event );
284   }
285 }
286
287 void EventHandler::SendRotationRequestEvent( )
288 {
289   if( mRotationObserver != NULL )
290   {
291     mRotationObserver->OnRotationRequest( );
292   }
293 }
294
295 void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp)
296 {
297   Integration::Point convertedPoint( point );
298   SendEvent( convertedPoint, timeStamp );
299 }
300
301 void EventHandler::FeedWheelEvent( WheelEvent& wheelEvent )
302 {
303   SendWheelEvent( wheelEvent );
304 }
305
306 void EventHandler::FeedKeyEvent( KeyEvent& event )
307 {
308   SendEvent( event );
309 }
310
311 void EventHandler::FeedEvent( Integration::Event& event )
312 {
313   mCoreEventInterface.QueueCoreEvent( event );
314   mCoreEventInterface.ProcessCoreEvents();
315 }
316
317 void EventHandler::Reset()
318 {
319   mCombiner.Reset();
320
321   // Any touch listeners should be told of the interruption.
322   Integration::TouchEvent event;
323   Integration::Point point;
324   point.SetState( PointState::INTERRUPTED );
325   event.AddPoint( point );
326
327   // First the touch event & related gesture events are queued
328   mCoreEventInterface.QueueCoreEvent( event );
329   mGestureManager.SendEvent( event );
330
331   // Next the events are processed with a single call into Core
332   mCoreEventInterface.ProcessCoreEvents();
333 }
334
335 void EventHandler::Pause()
336 {
337   mPaused = true;
338   Reset();
339 }
340
341 void EventHandler::Resume()
342 {
343   mPaused = false;
344   Reset();
345 }
346
347 void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
348 {
349   mDragAndDropDetector = detector;
350 }
351
352 void EventHandler::SetRotationObserver( RotationObserver* observer )
353 {
354   mRotationObserver = observer;
355 }
356
357 } // namespace Adaptor
358
359 } // namespace Internal
360
361 } // namespace Dali