Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / FUi_UiTouchEvent.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://floralicense.org/license/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file                FUi_UiTouchEvent.cpp
19  * @brief               This is the implementation file for the _UiTouchEvent class.
20  */
21
22 #include <FBaseResult.h>
23 #include <FBaseColIEnumeratorT.h>
24 #include <FBaseSysLog.h>
25 #include "FUi_UiTouchEvent.h"
26 #include "FUi_ITouchEventListener.h"
27 #include "FUi_ITouchEventPreviewer.h"
28 #include "FUi_Control.h"
29 #include "FUi_ControlManager.h"
30 #include "FUi_TouchGestureDetector.h"
31 #include "FUi_TouchManager.h"
32 #include "FUi_ITouchGestureDelegate.h"
33 #include "FUi_ControlImpl.h"
34 #include "FUi_TouchEventArg.h"
35
36 using namespace std::tr1;
37 using namespace Tizen::Base::Collection;
38 using namespace Tizen::Graphics;
39
40 namespace Tizen { namespace Ui
41 {
42 _TouchInfo::_TouchInfo(void)
43         : __pointId(0)
44         , __touchStatus(_TOUCH_PRESSED)
45         , __currentPosition(0, 0)
46         , __isFlicked(false)
47         , __timeStamp(0)
48 {
49 }
50
51 _TouchInfo::_TouchInfo(unsigned long pointId, _TouchStatus status, const Tizen::Graphics::Point& current, const bool isFlick, long long timeStamp)
52         : __pointId(pointId)
53         , __touchStatus(status)
54         , __currentPosition(current)
55         , __isFlicked(isFlick)
56         , __timeStamp(timeStamp)
57 {
58 }
59
60 _TouchInfo::_TouchInfo(const _TouchInfo& rhs)
61         : __pointId(rhs.__pointId)
62         , __touchStatus(rhs.__touchStatus)
63         , __currentPosition(rhs.__currentPosition)
64         , __isFlicked(rhs.__isFlicked)
65         , __timeStamp(rhs.__timeStamp)
66 {
67 }
68
69 _TouchInfo&
70 _TouchInfo::operator =(const _TouchInfo& rhs)
71 {
72         if (this != &rhs)
73         {
74                 __pointId = rhs.__pointId;
75                 __touchStatus = rhs.__touchStatus;
76                 __currentPosition = rhs.__currentPosition;
77                 __isFlicked = rhs.__isFlicked;
78                 __timeStamp = rhs.__timeStamp;
79         }
80
81         return *this;
82 }
83
84 _TouchInfo::~_TouchInfo(void)
85 {
86 }
87
88 _TouchStatus
89 _TouchInfo::GetTouchStatus(void) const
90 {
91         return __touchStatus;
92 }
93
94 Tizen::Graphics::Point
95 _TouchInfo::GetCurrentPosition(void) const
96 {
97         return __currentPosition;
98 }
99
100 unsigned long
101 _TouchInfo::GetPointId(void) const
102 {
103         return __pointId;
104 }
105
106 bool
107 _TouchInfo::IsFlicked(void) const
108 {
109         return __isFlicked;
110 }
111
112 long long
113 _TouchInfo::GetTimeStamp(void) const
114 {
115         return __timeStamp;
116 }
117
118 void
119 _TouchInfo::SetTouchInfo(unsigned long pointId, _TouchStatus status, Tizen::Graphics::Point& current, bool isFlick, long long timeStamp)
120 {
121         __pointId = pointId;
122         __touchStatus = status;
123         __currentPosition = current;
124         __isFlicked = isFlick;
125         __timeStamp = timeStamp;
126 }
127
128 _UiTouchEvent::_UiTouchEvent(const _UiObjectHandle& destination, const _TouchInfo& touchInfo, _UiEventRouteType routeType, const _UiObjectHandle& source)
129         : _UiEvent(destination, source, routeType)
130         , __touchInfo(touchInfo)
131         , __pForcedGestureList(new (std::nothrow) LinkedListT<_Control*>)
132 {
133 }
134
135 _UiTouchEvent::~_UiTouchEvent(void)
136 {
137 }
138
139 _UiTouchEvent::_UiTouchEvent(const _UiTouchEvent& rhs)
140         : _UiEvent(rhs)
141         , __touchInfo(rhs.__touchInfo)
142         , __pForcedGestureList(rhs.__pForcedGestureList)
143 {
144 }
145
146 _UiTouchEvent&
147 _UiTouchEvent::operator =(const _UiTouchEvent& rhs)
148 {
149         _UiEvent::operator =(rhs);
150
151         if (this != &rhs)
152         {
153                 __touchInfo = rhs.__touchInfo;
154                 __pForcedGestureList = rhs.__pForcedGestureList;
155         }
156
157         return *this;
158 }
159
160 const _TouchInfo*
161 _UiTouchEvent::GetTouchInfo(void) const
162 {
163         return &__touchInfo;
164 }
165
166 _UiTouchEvent*
167 _UiTouchEvent::CloneN(void) const
168 {
169         return new (std::nothrow) _UiTouchEvent(*this);
170 }
171
172 _UiEventType
173 _UiTouchEvent::GetEventType(void) const
174 {
175         return _UI_EVENT_TOUCH;
176 }
177
178 result
179 _UiTouchEvent::OnPreviewEventProcessing(const _Control& control, bool& isFiltered)
180 {
181         result r = E_SUCCESS;
182
183         const _TouchInfo* pTouchInfo = GetTouchInfo();
184         SysTryReturn(NID_UI, pTouchInfo, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
185
186         if (!control.IsInputEnabled() && pTouchInfo->GetTouchStatus() != _TOUCH_CANCELED)
187         {
188                 return E_SUCCESS;
189         }
190
191         if ((!ExistGlobalGesture() || GetAccessibilityEvent()) && !isFiltered)
192         {
193                 _ITouchEventPreviewer* pTouchEventPreviewer = control.GetEventPreviewer<_UI_EVENT_TOUCH, _ITouchEventPreviewer*>();
194                 SysTryReturn(NID_UI, pTouchEventPreviewer, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
195
196                 r = FirePreviewListener(pTouchEventPreviewer, &control, isFiltered);
197         }
198
199         return r;
200 }
201
202 result
203 _UiTouchEvent::OnEventProcessing(const _Control& control, bool& isFiltered)
204 {
205         result r = E_SUCCESS;
206
207         bool doesControlExist = false;
208
209         const _TouchInfo* pTouchInfo = GetTouchInfo();
210         SysTryReturn(NID_UI, pTouchInfo, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
211
212         if (!control.IsInputEnabled() && pTouchInfo->GetTouchStatus() != _TOUCH_CANCELED)
213         {
214                 return E_SUCCESS;
215         }
216
217         if ((!ExistGlobalGesture() || GetAccessibilityEvent()) && !isFiltered)
218         {
219                 ProcessGesture(control, isFiltered);
220         }
221         else if (isFiltered)
222         {
223                 doesControlExist = __pForcedGestureList->Contains(const_cast<_Control*>(&control));
224
225                 if (doesControlExist)
226                 {
227                         bool isForcedFiltered = false;
228                         ProcessGesture(control, isForcedFiltered);
229
230                         if (isForcedFiltered)
231                         {
232                                 isFiltered = true;
233                         }
234                 }
235         }
236
237         if ((!ExistGlobalGesture() || GetAccessibilityEvent()) && !isFiltered)
238         {
239                 _ITouchEventListener* pTouchEventListener = control.GetPropagatedTouchEventListener();
240                 SysTryReturn(NID_UI, pTouchEventListener, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
241
242                 r = FireListener(pTouchEventListener, &control, true, isFiltered);
243         }
244
245         return r;
246 }
247
248 result
249 _UiTouchEvent::OnListenerProcessing(const _IUiEventListener& listener, bool& isFiltered)
250 {
251         _ITouchEventListener* pTouchEventListener = dynamic_cast <_ITouchEventListener*>(const_cast <_IUiEventListener*>(&listener));
252         SysTryReturn(NID_UI, pTouchEventListener, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
253
254         return FireListener(pTouchEventListener, null, true, isFiltered);
255 }
256
257 result
258 _UiTouchEvent::OnEventHandled(const _Control& control)
259 {
260         _Control* pTarget = const_cast<_Control*>(GetControl(GetDestination()));
261         SysTryReturn(NID_UI, pTarget, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
262
263         const _TouchInfo* pTouchInfo = GetTouchInfo();
264         SysTryReturn(NID_UI, pTouchInfo, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
265
266         result r = E_SUCCESS;
267
268         switch (pTouchInfo->GetTouchStatus())
269         {
270         case _TOUCH_PRESSED:
271                 pTarget->GetPropagatedTouchEventListener()->OnTouchPressHandled(control);
272                 break;
273
274         case _TOUCH_MOVED:
275                 pTarget->GetPropagatedTouchEventListener()->OnTouchMoveHandled(control);
276                 break;
277
278         case _TOUCH_RELEASED:
279                 pTarget->GetPropagatedTouchEventListener()->OnTouchReleaseHandled(control);
280                 break;
281
282         case _TOUCH_CANCELED:
283                 pTarget->GetPropagatedTouchEventListener()->OnTouchCancelHandled(control);
284                 break;
285
286         default:
287                 r = E_SYSTEM;
288                 break;
289         }
290
291         return r;
292 }
293
294 result
295 _UiTouchEvent::FireListener(const _ITouchEventListener* pListener, const _Control* pControl,  bool isTouchEvent, bool& isFiltered)
296 {
297         _ITouchEventListener* pTouchEventListener = const_cast <_ITouchEventListener*>(pListener);
298         SysTryReturn(NID_UI, pTouchEventListener, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
299
300         result r = E_SUCCESS;
301
302         const _TouchInfo* pTouchInfo = GetTouchInfo();
303         SysTryReturn(NID_UI, pTouchInfo, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
304
305         const _Control* pTarget = GetControl(GetOriginalDestination());
306         if (pTarget == null)
307         {
308                 SysLog(NID_UI, "pTarget == null, Call ResetTouchInfo.");
309                 _TouchManager* pTouchManager = _TouchManager::GetInstance();
310                 pTouchManager->ResetTouchInfo();
311
312                 return E_SUCCESS;
313
314 }
315
316         if (ResetTouchInfo(pTarget, *pTouchInfo) == E_SUCCESS)
317         {
318                 isFiltered = true;
319                 return E_SYSTEM;
320         }
321
322         Point point(0, 0);
323
324         if (pControl)
325         {
326                 _TouchManager* pTouchManager = _TouchManager::GetInstance();
327                 SysAssert(pTouchManager != null)
328
329                 point = GetRelativePoint(*pControl, pTouchInfo->GetCurrentPosition());
330
331                 if (isTouchEvent && (pTouchInfo->GetTouchStatus() != _TOUCH_CANCELED))
332                 {
333                         if (!pTouchManager->IsTouchAllowed() || (pTouchManager->IsTouchAllowed() && pTouchManager->IsTouchCanceledOnGestureSuccess())
334                                 || (!pControl->IsMultiTouchEnabled() && pTouchInfo->GetPointId() > 0))
335                         {
336                                 isFiltered = true;
337                                 return E_SUCCESS;
338                         }
339                 }
340         }
341         else
342         {
343                 point = GetRelativePoint(*pTarget, pTouchInfo->GetCurrentPosition());
344         }
345
346         _TouchInfo touchInfo(pTouchInfo->GetPointId(), pTouchInfo->GetTouchStatus(), point, false, pTouchInfo->GetTimeStamp());
347
348         switch (touchInfo.GetTouchStatus())
349         {
350         case _TOUCH_PRESSED:
351                 isFiltered = pTouchEventListener->OnTouchPressed(*pTarget, touchInfo);
352                 break;
353
354         case _TOUCH_RELEASED:
355                 isFiltered = pTouchEventListener->OnTouchReleased(*pTarget, touchInfo);
356                 break;
357
358         case _TOUCH_MOVED:
359                 isFiltered = pTouchEventListener->OnTouchMoved(*pTarget, touchInfo);
360                 break;
361
362                 // 2.0 compatibility for touch simulate
363         case _TOUCH_LONG_PRESSED:
364                 // fall through
365         case _TOUCH_DOUBLE_PRESSED:
366                 {
367                         void* pData = pTarget->GetUserData();
368                         if (pData)
369                         {
370                                 _ControlImpl* pTargetImpl = static_cast<_ControlImpl*>(pData);
371                                 if (pTargetImpl)
372                                 {
373                                         pTargetImpl->GenerateTouchEvent(touchInfo);
374                                 }
375                         }
376                 }
377                 break;
378
379         case _TOUCH_CANCELED:
380                 isFiltered = pTouchEventListener->OnTouchCanceled(*pTarget, touchInfo);
381                 break;
382
383         default:
384                 r = E_SYSTEM;
385         }
386
387         return r;
388 }
389
390 result
391 _UiTouchEvent::FirePreviewListener(const _ITouchEventPreviewer* pListener, const _Control* pControl, bool& isFiltered)
392 {
393         _ITouchEventPreviewer* pTouchEventPreviewer = const_cast <_ITouchEventPreviewer*>(pListener);
394         SysTryReturn(NID_UI, pTouchEventPreviewer, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
395
396         result r = E_SUCCESS;
397
398         const _TouchInfo* pTouchInfo = GetTouchInfo();
399         SysTryReturn(NID_UI, pTouchInfo, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
400
401         const _Control* pTarget = GetControl(GetDestination());
402
403         Point point = GetRelativePoint(*pControl, pTouchInfo->GetCurrentPosition());
404
405         _TouchInfo touchInfo(pTouchInfo->GetPointId(), pTouchInfo->GetTouchStatus(), point, false, pTouchInfo->GetTimeStamp());
406
407         _UiTouchEventDelivery eventDelivery = _UI_TOUCH_EVENT_DELIVERY_NO;
408
409         //condition 1) if target is not enabled multi touch, point id should be 0
410         //2) target is enabled multi touch
411         switch (touchInfo.GetTouchStatus())
412         {
413         case _TOUCH_PRESSED:
414                 eventDelivery = pTouchEventPreviewer->OnPreviewTouchPressed(*pTarget, touchInfo);
415
416                 break;
417
418         case _TOUCH_RELEASED:
419                 eventDelivery = pTouchEventPreviewer->OnPreviewTouchReleased(*pTarget, touchInfo);
420
421                 break;
422
423         case _TOUCH_MOVED:
424                 eventDelivery = pTouchEventPreviewer->OnPreviewTouchMoved(*pTarget, touchInfo);
425
426                 break;
427
428         case _TOUCH_CANCELED:
429                 eventDelivery = pTouchEventPreviewer->OnPreviewTouchCanceled(*pTarget, touchInfo);
430                 break;
431
432         default:
433                 r = E_SYSTEM;
434                 break;
435         }
436
437         if (eventDelivery != _UI_TOUCH_EVENT_DELIVERY_NO)
438         {
439                 // isFiltered = (eventDelivery == _UI_TOUCH_EVENT_DELIVERY_FORCED_YES);
440
441                 // if (isFiltered)
442                 if (eventDelivery == _UI_TOUCH_EVENT_DELIVERY_FORCED_YES)
443                 {
444                         __pForcedGestureList->Add(const_cast<_Control*>(pControl));
445                 }
446         }
447         else
448         {
449                 isFiltered = true;
450         }
451
452         return r;
453 }
454
455 result
456 _UiTouchEvent::ProcessGesture(const _Control& control, bool& isFiltered)
457 {
458         if (control.IsSendingDelayedEvent())
459         {
460                 return E_SUCCESS;
461         }
462
463         IListT<_TouchGestureDetector*>* pGestureList = control.GetGestureDetectorList();
464         if (!pGestureList || (pGestureList && (pGestureList->GetCount() <= 0)))
465         {
466                 return E_SUCCESS;
467         }
468
469         IEnumeratorT<_TouchGestureDetector*>* pEnumerator = pGestureList->GetEnumeratorN();
470         SysTryReturn(NID_UI, pEnumerator, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occurred.");
471
472         while (pEnumerator->MoveNext() == E_SUCCESS)
473         {
474                 _TouchGestureDetector* pGestureDetector = null;
475                 pEnumerator->GetCurrent(pGestureDetector);
476
477                 if (!pGestureDetector)
478                 {
479                         continue;
480                 }
481
482                 _ITouchGestureDelegate* pDelegator = pGestureDetector->GetDelegate();
483                 if (pDelegator)
484                 {
485                         FireListener(pDelegator, &control, false, isFiltered);
486                 }
487         }
488
489         delete pEnumerator;
490         return E_SUCCESS;
491 }
492
493 Point
494 _UiTouchEvent::GetRelativePoint(const _Control& control, const Point& point) const
495 {
496         Point relativePoint(point);
497         Rectangle absRect = control.GetAbsoluteBounds();
498
499         relativePoint.x -= absRect.x;
500         relativePoint.y -= absRect.y;
501
502         return relativePoint;
503 }
504
505 result
506 _UiTouchEvent::ResetTouchInfo(const _Control* pControl, const _TouchInfo& touchInfo)
507 {
508         _TouchManager* pTouchManager = _TouchManager::GetInstance();
509         SysTryReturnResult(NID_UI, pTouchManager, E_SYSTEM, "[E_SYSTEM] System error occurred. ");
510
511         if (pControl == null)
512         {
513                 if (touchInfo.GetTouchStatus() == _TOUCH_RELEASED)
514                 {
515                         pTouchManager->ResetTouchInfo();
516                 }
517
518                 return E_SUCCESS;
519         }
520
521         return E_INVALID_CONDITION;
522 }
523
524 bool
525 _UiTouchEvent::ExistGlobalGesture(void)
526 {
527         _ControlManager* pControlManager = _ControlManager::GetInstance();
528         SysTryReturn(NID_UI, pControlManager, false, E_SYSTEM, "[E_SYSTEM] System error occurred.");
529
530         bool exist = false;
531
532         IListT<_TouchGestureDetector*>* pGestureList = pControlManager->GetGestureDetectorList();
533         if (pGestureList && (pGestureList->GetCount() > 0))
534         {
535                 exist = true;
536         }
537
538         return exist;
539 }
540
541 }} // Tizen::Ui