Merge lp:~thomas-voss/grail/rework_cosmetics into lp:~chasedouglas/grail/rework
- rework_cosmetics
- Merge into rework
Proposed by
Thomas Voß
Status: | Rejected |
---|---|
Rejected by: | Chase Douglas |
Proposed branch: | lp:~thomas-voss/grail/rework_cosmetics |
Merge into: | lp:~chasedouglas/grail/rework |
Diff against target: |
4720 lines (+2413/-2104) 13 files modified
include/utouch/grail.h (+7/-7) src/v3/event.cpp (+55/-36) src/v3/event.h (+24/-19) src/v3/gesture.cpp (+246/-181) src/v3/gesture.h (+42/-45) src/v3/handle.cpp (+345/-313) src/v3/handle.h (+39/-40) src/v3/recognizer.cpp (+539/-490) src/v3/recognizer.h (+40/-53) src/v3/slice.cpp (+688/-551) src/v3/slice.h (+57/-65) src/v3/subscription.cpp (+288/-250) src/v3/subscription.h (+43/-54) |
To merge this branch: | bzr merge lp:~thomas-voss/grail/rework_cosmetics |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stephen M. Webb (community) | Needs Fixing | ||
Chase Douglas | Pending | ||
Review via email: mp+80954@code.launchpad.net |
Commit message
Description of the change
Wrapped up the actual implementation in namespace utouch::grail. PIMPL-ed classes and switched to opaque-pointers for the C interface.
To post a comment you must log in.
Unmerged revisions
- 241. By Thomas Voß
-
Modified: Reverted changes to initialization of limits.
- 240. By Thomas Voß
-
Cleaned up v3, introduced utouch::grail namespace and PIMPL-ed classes.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'include/utouch/grail.h' | |||
2 | --- include/utouch/grail.h 2011-10-19 21:39:17 +0000 | |||
3 | +++ include/utouch/grail.h 2011-11-01 21:20:40 +0000 | |||
4 | @@ -41,13 +41,13 @@ | |||
5 | 41 | */ | 41 | */ |
6 | 42 | 42 | ||
7 | 43 | /** An object for the context of the uTouch Frame instance */ | 43 | /** An object for the context of the uTouch Frame instance */ |
9 | 44 | typedef struct UGHandle_* UGHandle; | 44 | typedef void * UGHandle; |
10 | 45 | /** An object for a gesture subscription */ | 45 | /** An object for a gesture subscription */ |
12 | 46 | typedef struct UGSubscription_* UGSubscription; | 46 | typedef void * UGSubscription; |
13 | 47 | /** An object for an event */ | 47 | /** An object for an event */ |
15 | 48 | typedef const struct UGEvent_* UGEvent; | 48 | typedef const void * UGEvent; |
16 | 49 | /** An object for a gesture state in time */ | 49 | /** An object for a gesture state in time */ |
18 | 50 | typedef const struct UGSlice_* UGSlice; | 50 | typedef void * UGSlice; |
19 | 51 | 51 | ||
20 | 52 | /** The status code denoting the result of a function call */ | 52 | /** The status code denoting the result of a function call */ |
21 | 53 | typedef enum UGStatus { | 53 | typedef enum UGStatus { |
22 | @@ -400,7 +400,7 @@ | |||
23 | 400 | * @param [out] event The retrieved event | 400 | * @param [out] event The retrieved event |
24 | 401 | * @return UGStatusSuccess or UGStatusErrorNoEvent | 401 | * @return UGStatusSuccess or UGStatusErrorNoEvent |
25 | 402 | */ | 402 | */ |
27 | 403 | UGStatus grail_get_event(UGHandle handle, UGEvent *event); | 403 | UGStatus grail_get_event(UGHandle handle, UGEvent * event ); |
28 | 404 | 404 | ||
29 | 405 | /** | 405 | /** |
30 | 406 | * Release an event back to the uTouch Grail context | 406 | * Release an event back to the uTouch Grail context |
31 | @@ -499,7 +499,7 @@ | |||
32 | 499 | * @param [in] event The event object | 499 | * @param [in] event The event object |
33 | 500 | * @return The type of the event | 500 | * @return The type of the event |
34 | 501 | */ | 501 | */ |
36 | 502 | UGEventType grail_event_get_type(const UGEvent event); | 502 | UGEventType grail_event_get_type( UGEvent event); |
37 | 503 | 503 | ||
38 | 504 | /** | 504 | /** |
39 | 505 | * Get the time of an event | 505 | * Get the time of an event |
40 | @@ -507,7 +507,7 @@ | |||
41 | 507 | * @param [in] event The event object | 507 | * @param [in] event The event object |
42 | 508 | * @return The time of the event | 508 | * @return The time of the event |
43 | 509 | */ | 509 | */ |
45 | 510 | uint64_t grail_event_get_time(const UGEvent event); | 510 | uint64_t grail_event_get_time(UGEvent event); |
46 | 511 | 511 | ||
47 | 512 | /** | 512 | /** |
48 | 513 | * Get the ID of a gesture from a slice | 513 | * Get the ID of a gesture from a slice |
49 | 514 | 514 | ||
50 | === modified file 'src/v3/event.cpp' | |||
51 | --- src/v3/event.cpp 2011-10-13 22:56:46 +0000 | |||
52 | +++ src/v3/event.cpp 2011-11-01 21:20:40 +0000 | |||
53 | @@ -1,6 +1,6 @@ | |||
54 | 1 | /***************************************************************************** | 1 | /***************************************************************************** |
55 | 2 | * | 2 | * |
57 | 3 | * utouch-grail - Multitouch Gesture Recognition Library | 3 | * Utouch-grail - Multitouch Gesture Recognition Library |
58 | 4 | * | 4 | * |
59 | 5 | * Copyright (C) 2011 Canonical Ltd. | 5 | * Copyright (C) 2011 Canonical Ltd. |
60 | 6 | * | 6 | * |
61 | @@ -21,52 +21,71 @@ | |||
62 | 21 | 21 | ||
63 | 22 | #include "event.h" | 22 | #include "event.h" |
64 | 23 | 23 | ||
66 | 24 | #include <assert.h> | 24 | #include <cassert> |
67 | 25 | 25 | ||
68 | 26 | #include "slice.h" | 26 | #include "slice.h" |
69 | 27 | 27 | ||
94 | 28 | UGEvent_::UGEvent_(const SharedUGSlice_& slice) | 28 | namespace utouch { |
95 | 29 | : slice_(slice), | 29 | namespace grail { |
96 | 30 | time_(slice->time()) { | 30 | |
97 | 31 | } | 31 | struct UGEvent::Private { |
98 | 32 | 32 | ||
99 | 33 | UGStatus UGEvent_::GetProperty(UGEventProperty property, void* data) const { | 33 | Private( const SharedUGSlice & slice ) : slice_( slice ), |
100 | 34 | switch (property) { | 34 | time_( slice->time() ) { |
101 | 35 | case UGEventPropertyType: | 35 | } |
102 | 36 | *reinterpret_cast<UGEventType*>(data) = UGEventTypeSlice; | 36 | |
103 | 37 | return UGStatusSuccess; | 37 | const SharedUGSlice slice_; |
104 | 38 | 38 | const uint64_t time_; | |
105 | 39 | case UGEventPropertySlice: | 39 | }; |
106 | 40 | *reinterpret_cast<UGSlice*>(data) = slice_.get(); | 40 | |
107 | 41 | return UGStatusSuccess; | 41 | UGEvent::UGEvent(const SharedUGSlice & slice) |
108 | 42 | 42 | : d_( new Private( slice ) ) { | |
109 | 43 | case UGEventPropertyTime: | 43 | } |
110 | 44 | *reinterpret_cast<uint64_t*>(data) = time_; | 44 | |
111 | 45 | return UGStatusSuccess; | 45 | UGStatus UGEvent::GetProperty(UGEventProperty property, void* data) const { |
112 | 46 | } | 46 | assert( data == NULL ); |
113 | 47 | 47 | ||
114 | 48 | return UGStatusErrorUnknownProperty; | 48 | switch (property) { |
115 | 49 | } | 49 | case UGEventPropertyType: |
116 | 50 | 50 | *reinterpret_cast<UGEventType*>(data) = UGEventTypeSlice; | |
117 | 51 | extern "C" { | 51 | return UGStatusSuccess; |
118 | 52 | |||
119 | 53 | case UGEventPropertySlice: | ||
120 | 54 | *reinterpret_cast<UGSlice*>(data) = *d_->slice_.get(); | ||
121 | 55 | return UGStatusSuccess; | ||
122 | 56 | |||
123 | 57 | case UGEventPropertyTime: | ||
124 | 58 | *reinterpret_cast<uint64_t*>(data) = d_->time_; | ||
125 | 59 | return UGStatusSuccess; | ||
126 | 60 | } | ||
127 | 61 | |||
128 | 62 | return UGStatusErrorUnknownProperty; | ||
129 | 63 | } | ||
130 | 64 | } | ||
131 | 65 | |||
132 | 66 | } | ||
133 | 52 | 67 | ||
134 | 53 | UGStatus grail_event_get_property(const UGEvent event, UGEventProperty property, | 68 | UGStatus grail_event_get_property(const UGEvent event, UGEventProperty property, |
135 | 54 | void* data) { | 69 | void* data) { |
137 | 55 | return event->GetProperty(property, data); | 70 | assert( event == NULL ); |
138 | 71 | assert( data == NULL ); | ||
139 | 72 | |||
140 | 73 | return static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(property, data); | ||
141 | 56 | } | 74 | } |
142 | 57 | 75 | ||
143 | 58 | UGEventType grail_event_get_type(const UGEvent event) { | 76 | UGEventType grail_event_get_type(const UGEvent event) { |
148 | 59 | UGEventType type; | 77 | assert( event == NULL ); |
149 | 60 | UGStatus status = event->GetProperty(UGEventPropertyType, &type); | 78 | UGEventType type; |
150 | 61 | assert(status == UGStatusSuccess); | 79 | UGStatus status = static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(UGEventPropertyType, &type); |
151 | 62 | return type; | 80 | assert(status == UGStatusSuccess); |
152 | 81 | return type; | ||
153 | 63 | } | 82 | } |
154 | 64 | 83 | ||
155 | 65 | uint64_t grail_event_get_time(const UGEvent event) { | 84 | uint64_t grail_event_get_time(const UGEvent event) { |
160 | 66 | uint64_t time; | 85 | assert( event == NULL ); |
161 | 67 | UGStatus status = event->GetProperty(UGEventPropertyTime, &time); | 86 | uint64_t time; |
162 | 68 | assert(status == UGStatusSuccess); | 87 | UGStatus status = static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(UGEventPropertyTime, &time); |
163 | 69 | return time; | 88 | assert(status == UGStatusSuccess); |
164 | 89 | return time; | ||
165 | 70 | } | 90 | } |
166 | 71 | 91 | ||
167 | 72 | } // extern "C" | ||
168 | 73 | 92 | ||
169 | === modified file 'src/v3/event.h' | |||
170 | --- src/v3/event.h 2011-10-13 22:56:46 +0000 | |||
171 | +++ src/v3/event.h 2011-11-01 21:20:40 +0000 | |||
172 | @@ -24,26 +24,31 @@ | |||
173 | 24 | 24 | ||
174 | 25 | #include <memory> | 25 | #include <memory> |
175 | 26 | 26 | ||
177 | 27 | #include <stdint.h> | 27 | #include <cstdint> |
178 | 28 | 28 | ||
179 | 29 | #include "utouch/grail.h" | 29 | #include "utouch/grail.h" |
180 | 30 | 30 | ||
199 | 31 | class UGSlice_; | 31 | namespace utouch { |
200 | 32 | 32 | namespace grail { | |
201 | 33 | typedef std::shared_ptr<UGSlice_> SharedUGSlice_; | 33 | |
202 | 34 | 34 | class UGSlice; | |
203 | 35 | class UGEvent_ { | 35 | |
204 | 36 | public: | 36 | typedef std::shared_ptr<UGSlice> SharedUGSlice; |
205 | 37 | UGEvent_(const SharedUGSlice_& slice); | 37 | |
206 | 38 | 38 | class UGEvent { | |
207 | 39 | UGStatus GetProperty(UGEventProperty property, void* value) const; | 39 | public: |
208 | 40 | 40 | UGEvent(const SharedUGSlice & slice); | |
209 | 41 | UGEvent_(const UGEvent_&) = delete; | 41 | |
210 | 42 | void operator=(const UGEvent_&) = delete; | 42 | UGStatus GetProperty(UGEventProperty property, void* value) const; |
211 | 43 | 43 | ||
212 | 44 | private: | 44 | UGEvent(const UGEvent&) = delete; |
213 | 45 | const SharedUGSlice_ slice_; | 45 | void operator=(const UGEvent&) = delete; |
214 | 46 | const uint64_t time_; | 46 | |
215 | 47 | }; | 47 | protected: |
216 | 48 | 48 | struct Private; | |
217 | 49 | std::shared_ptr< Private > d_; | ||
218 | 50 | |||
219 | 51 | }; | ||
220 | 52 | } | ||
221 | 53 | } | ||
222 | 49 | #endif // UTOUCH_GRAIL_EVENT_H | 54 | #endif // UTOUCH_GRAIL_EVENT_H |
223 | 50 | 55 | ||
224 | === modified file 'src/v3/gesture.cpp' | |||
225 | --- src/v3/gesture.cpp 2011-10-20 22:19:11 +0000 | |||
226 | +++ src/v3/gesture.cpp 2011-11-01 21:20:40 +0000 | |||
227 | @@ -21,7 +21,7 @@ | |||
228 | 21 | 21 | ||
229 | 22 | #include "gesture.h" | 22 | #include "gesture.h" |
230 | 23 | 23 | ||
232 | 24 | #include <stdio.h> | 24 | #include <cstdio> |
233 | 25 | 25 | ||
234 | 26 | #include "utouch/grail.h" | 26 | #include "utouch/grail.h" |
235 | 27 | 27 | ||
236 | @@ -30,184 +30,249 @@ | |||
237 | 30 | #include "recognizer.h" | 30 | #include "recognizer.h" |
238 | 31 | #include "slice.h" | 31 | #include "slice.h" |
239 | 32 | 32 | ||
420 | 33 | Gesture::Gesture(Recognizer* recognizer, UGSubscription_* subscription, | 33 | namespace utouch { |
421 | 34 | TouchSet& touches, uint64_t start_time) | 34 | namespace grail { |
422 | 35 | : recognizer_(recognizer), | 35 | |
423 | 36 | id_(recognizer_->handle()->NewGestureID(recognizer_)), | 36 | struct Gesture::Private { |
424 | 37 | subscription_(subscription), | 37 | |
425 | 38 | touches_(touches), | 38 | Private( Recognizer * recognizer, |
426 | 39 | start_time_(start_time), | 39 | utouch::grail::UGSubscription * subscription, |
427 | 40 | recognized_(0), | 40 | TouchSet & touches, |
428 | 41 | canceled_(false), | 41 | uint64_t start_time ) |
429 | 42 | ended_(false) { | 42 | : recognizer_(recognizer), |
430 | 43 | } | 43 | id_(recognizer_->handle()->NewGestureID(recognizer_)), |
431 | 44 | 44 | subscription_(subscription), | |
432 | 45 | Gesture::Gesture(const Gesture* other_gesture, TouchSet& touches) | 45 | touches_(touches), |
433 | 46 | : recognizer_(other_gesture->recognizer_), | 46 | start_time_(start_time), |
434 | 47 | id_(recognizer_->handle()->NewGestureID(recognizer_)), | 47 | recognized_(0), |
435 | 48 | subscription_(other_gesture->subscription_), | 48 | canceled_(false), |
436 | 49 | touches_(touches), | 49 | ended_(false) { |
437 | 50 | start_time_(other_gesture->start_time_), | 50 | } |
438 | 51 | recognized_(other_gesture->recognized_), | 51 | |
439 | 52 | canceled_(false), | 52 | Private( const Gesture* other_gesture, TouchSet & touches ) |
440 | 53 | ended_(false) { | 53 | : recognizer_(other_gesture->d_->recognizer_), |
441 | 54 | } | 54 | id_(recognizer_->handle()->NewGestureID(recognizer_)), |
442 | 55 | 55 | subscription_(other_gesture->d_->subscription_), | |
443 | 56 | void Gesture::Update(UFEvent frame_event, TouchSet& modified_touches) { | 56 | touches_(touches), |
444 | 57 | if (ended_) { | 57 | start_time_(other_gesture->d_->start_time_), |
445 | 58 | if (recognized_ && IsOwned()) | 58 | recognized_(other_gesture->d_->recognized_), |
446 | 59 | FlushSlices(); | 59 | canceled_(false), |
447 | 60 | 60 | ended_(false) { | |
448 | 61 | return; | 61 | } |
449 | 62 | } | 62 | |
450 | 63 | 63 | Recognizer * recognizer_; | |
451 | 64 | UFFrame frame; | 64 | unsigned int id_; |
452 | 65 | UFStatus status = frame_event_get_property(frame_event, UFEventPropertyFrame, | 65 | utouch::grail::UGSubscription* subscription_; |
453 | 66 | &frame); | 66 | TouchSet touches_; |
454 | 67 | if (status != UFStatusSuccess) { | 67 | uint64_t start_time_; |
455 | 68 | fprintf(stderr, "Warning: failed to get frame from event\n"); | 68 | UGGestureTypeMask recognized_; |
456 | 69 | return; | 69 | std::queue<utouch::grail::SharedUGSlice> slices_; |
457 | 70 | } | 70 | utouch::grail::SharedUGSlice last_slice_; |
458 | 71 | 71 | bool canceled_; | |
459 | 72 | TouchSet ended_touches; | 72 | bool ended_; |
460 | 73 | bool touch_found = false; | 73 | std::map<unsigned int, float> angles_; |
461 | 74 | for (unsigned int touch_id : modified_touches) { | 74 | }; |
462 | 75 | if (touches_.find(touch_id) != touches_.end()) | 75 | |
463 | 76 | touch_found = true; | 76 | Gesture::Gesture(Recognizer* recognizer, utouch::grail::UGSubscription* subscription, |
464 | 77 | else | 77 | TouchSet& touches, uint64_t start_time) |
465 | 78 | continue; | 78 | : d_( new Private( recognizer, subscription, touches, start_time ) ) { |
466 | 79 | 79 | } | |
467 | 80 | UFTouch touch; | 80 | |
468 | 81 | status = frame_frame_get_touch_by_id(frame, &touch_id, &touch); | 81 | Gesture::Gesture(const Gesture* other_gesture, TouchSet& touches) |
469 | 82 | if (status != UFStatusSuccess) { | 82 | : d_( new Private( other_gesture, touches ) ) { |
470 | 83 | fprintf(stderr, "Warning: failed to get touch from frame\n"); | 83 | } |
471 | 84 | return; | 84 | |
472 | 85 | } | 85 | void Gesture::Update(UFEvent frame_event, TouchSet& modified_touches) { |
473 | 86 | 86 | if ( d_->ended_) { | |
474 | 87 | UFTouchState state = frame_touch_get_state(touch); | 87 | if (d_->recognized_ && IsOwned()) |
475 | 88 | int owned; | 88 | FlushSlices(); |
476 | 89 | status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned); | 89 | |
477 | 90 | if (status != UFStatusSuccess) { | 90 | return; |
478 | 91 | fprintf(stderr, "Warning: failed to get touch from frame\n"); | 91 | } |
479 | 92 | return; | 92 | |
480 | 93 | } | 93 | UFFrame frame; |
481 | 94 | 94 | UFStatus status = frame_event_get_property(frame_event, UFEventPropertyFrame, | |
482 | 95 | if (state == UFTouchStateEnd) { | 95 | &frame); |
483 | 96 | if (owned) { | 96 | if (status != UFStatusSuccess) { |
484 | 97 | ended_touches.insert(touch_id); | 97 | fprintf(stderr, "Warning: failed to get frame from event\n"); |
485 | 98 | } else { | 98 | return; |
486 | 99 | canceled_ = true; | 99 | } |
487 | 100 | break; | 100 | |
488 | 101 | } | 101 | TouchSet ended_touches; |
489 | 102 | } | 102 | bool touch_found = false; |
490 | 103 | } | 103 | for (unsigned int touch_id : modified_touches) { |
491 | 104 | 104 | if (d_->touches_.find(touch_id) != d_->touches_.end()) | |
492 | 105 | if (!touch_found || canceled_) | 105 | touch_found = true; |
493 | 106 | return; | 106 | else |
494 | 107 | 107 | continue; | |
495 | 108 | if (!last_slice_) { | 108 | |
496 | 109 | UGSlice_* slice = UGSlice_::NewUGSlice_(shared_from_this(), frame_event, | 109 | UFTouch touch; |
497 | 110 | touches_, recognized_); | 110 | status = frame_frame_get_touch_by_id(frame, &touch_id, &touch); |
498 | 111 | if (!slice) | 111 | if (status != UFStatusSuccess) { |
499 | 112 | return; | 112 | fprintf(stderr, "Warning: failed to get touch from frame\n"); |
500 | 113 | last_slice_ = SharedUGSlice_(slice); | 113 | return; |
501 | 114 | } else { | 114 | } |
502 | 115 | UGSlice_* slice = UGSlice_::NewUGSlice_(last_slice_, frame_event, touches_); | 115 | |
503 | 116 | if (!slice) | 116 | UFTouchState state = frame_touch_get_state(touch); |
504 | 117 | return; | 117 | int owned; |
505 | 118 | last_slice_ = SharedUGSlice_(slice); | 118 | status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned); |
506 | 119 | } | 119 | if (status != UFStatusSuccess) { |
507 | 120 | 120 | fprintf(stderr, "Warning: failed to get touch from frame\n"); | |
508 | 121 | slices_.push(last_slice_); | 121 | return; |
509 | 122 | 122 | } | |
510 | 123 | for (unsigned int touch_id : ended_touches) | 123 | |
511 | 124 | touches_.erase(touch_id); | 124 | if (state == UFTouchStateEnd) { |
512 | 125 | 125 | if (owned) { | |
513 | 126 | if (recognized_ != subscription_->mask()) | 126 | ended_touches.insert(touch_id); |
514 | 127 | recognized_ |= last_slice_->CheckRecognition(*subscription_); | 127 | } else { |
515 | 128 | 128 | d_->canceled_ = true; | |
516 | 129 | if (recognized_ && IsOwned()) | 129 | break; |
517 | 130 | FlushSlices(); | 130 | } |
518 | 131 | 131 | } | |
519 | 132 | ended_ = (last_slice_->state() == UGGestureStateEnd); | 132 | } |
520 | 133 | if (ended_) | 133 | |
521 | 134 | last_slice_.reset(); | 134 | if (!touch_found || d_->canceled_) |
522 | 135 | } | 135 | return; |
523 | 136 | 136 | ||
524 | 137 | bool Gesture::IsOwned() const { | 137 | /* TODO |
525 | 138 | /* The only way we could reach here and not have any slices in the queue is | 138 | if (!last_slice_) { |
526 | 139 | * if we already flushed the queue, which is only done if we own the touches. | 139 | utouch::grail::UGSlice * slice = utouch::grail::UGSlice::NewUGSlice( shared_from_this(), |
527 | 140 | */ | 140 | frame_event, |
528 | 141 | if (slices_.empty()) | 141 | touches_, |
529 | 142 | return true; | 142 | recognized_ |
530 | 143 | 143 | ); | |
531 | 144 | for (unsigned int touch_id : slices_.front()->touches()) { | 144 | |
532 | 145 | UFTouch touch; | 145 | if (!slice) |
533 | 146 | UFStatus status = frame_frame_get_touch_by_id(slices_.back()->frame(), | 146 | return; |
534 | 147 | &touch_id, &touch); | 147 | last_slice_ = utouch::grail::SharedUGSlice(slice); |
535 | 148 | if (status != UFStatusSuccess) { | 148 | } else { |
536 | 149 | fprintf(stderr, "Warning: failed to get touch from frame\n"); | 149 | // TODO |
537 | 150 | return false; | 150 | // utouch::grail::UGSlice * slice = utouch::grail::UGSlice::NewUGSlice(last_slice_, frame_event, touches_); |
538 | 151 | } | 151 | if (!slice) |
539 | 152 | 152 | return; | |
540 | 153 | int owned; | 153 | last_slice_ = utouch::grail::SharedUGSlice(slice); |
541 | 154 | status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned); | 154 | }*/ |
542 | 155 | if (status != UFStatusSuccess) { | 155 | |
543 | 156 | fprintf(stderr, "Warning: failed to get ownership property from touch\n"); | 156 | d_->slices_.push(d_->last_slice_); |
544 | 157 | return false; | 157 | |
545 | 158 | } | 158 | for (unsigned int touch_id : ended_touches) |
546 | 159 | 159 | d_->touches_.erase(touch_id); | |
547 | 160 | if (!owned) | 160 | |
548 | 161 | return false; | 161 | if ( d_->recognized_ != d_->subscription_->mask()) |
549 | 162 | } | 162 | d_->recognized_ |= d_->last_slice_->CheckRecognition(*d_->subscription_); |
550 | 163 | 163 | ||
551 | 164 | return true; | 164 | if (d_->recognized_ && IsOwned()) |
552 | 165 | } | 165 | FlushSlices(); |
553 | 166 | 166 | ||
554 | 167 | void Gesture::FlushSlices() { | 167 | d_->ended_ = (d_->last_slice_->state() == UGGestureStateEnd); |
555 | 168 | while (!slices_.empty()) { | 168 | if (d_->ended_) |
556 | 169 | UGEvent_* event = new UGEvent_(slices_.front()); | 169 | d_->last_slice_.reset(); |
557 | 170 | slices_.front()->ReferenceGesture(); | 170 | } |
558 | 171 | recognizer_->handle()->EnqueueEvent(event); | 171 | |
559 | 172 | slices_.pop(); | 172 | bool Gesture::IsOwned() const { |
560 | 173 | } | 173 | /* The only way we could reach here and not have any slices in the queue is |
561 | 174 | } | 174 | * if we already flushed the queue, which is only done if we own the touches. |
562 | 175 | 175 | */ | |
563 | 176 | uint64_t Gesture::Timeout() const { | 176 | if (d_->slices_.empty()) |
564 | 177 | if (recognized_) | 177 | return true; |
565 | 178 | return 0; | 178 | |
566 | 179 | 179 | for (unsigned int touch_id : d_->slices_.front()->touches()) { | |
567 | 180 | uint64_t time = 0; | 180 | UFTouch touch; |
568 | 181 | if ((subscription_->mask() & UGGestureTypeDrag) && | 181 | UFStatus status = frame_frame_get_touch_by_id(d_->slices_.back()->frame(), |
569 | 182 | subscription_->drag().timeout() > time) | 182 | &touch_id, &touch); |
570 | 183 | time = subscription_->drag().timeout(); | 183 | if (status != UFStatusSuccess) { |
571 | 184 | if ((subscription_->mask() & UGGestureTypePinch) && | 184 | fprintf(stderr, "Warning: failed to get touch from frame\n"); |
572 | 185 | subscription_->pinch().timeout() > time) | 185 | return false; |
573 | 186 | time = subscription_->pinch().timeout(); | 186 | } |
574 | 187 | if ((subscription_->mask() & UGGestureTypeRotate) && | 187 | |
575 | 188 | subscription_->rotate().timeout() > time) | 188 | int owned; |
576 | 189 | time = subscription_->rotate().timeout(); | 189 | status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned); |
577 | 190 | if ((subscription_->mask() & UGGestureTypeTap) && | 190 | if (status != UFStatusSuccess) { |
578 | 191 | subscription_->tap().timeout() > time) | 191 | fprintf(stderr, "Warning: failed to get ownership property from touch\n"); |
579 | 192 | time = subscription_->tap().timeout(); | 192 | return false; |
580 | 193 | 193 | } | |
581 | 194 | return time; | 194 | |
582 | 195 | } | 195 | if (!owned) |
583 | 196 | 196 | return false; | |
584 | 197 | float Gesture::AngleForTouch(unsigned int touch_id) const { | 197 | } |
585 | 198 | auto it = angles_.find(touch_id); | 198 | |
586 | 199 | if (it != angles_.end()) | 199 | return true; |
587 | 200 | return it->second; | 200 | } |
588 | 201 | 201 | ||
589 | 202 | return 0; | 202 | void Gesture::FlushSlices() { |
590 | 203 | } | 203 | while (!d_->slices_.empty()) { |
591 | 204 | 204 | utouch::grail::UGEvent * event = new utouch::grail::UGEvent(d_->slices_.front()); | |
592 | 205 | void Gesture::SetAngleForTouch(unsigned int touch_id, float angle) { | 205 | d_->slices_.front()->ReferenceGesture(); |
593 | 206 | angles_[touch_id] = angle; | 206 | d_->recognizer_->handle()->EnqueueEvent(event); |
594 | 207 | } | 207 | d_->slices_.pop(); |
595 | 208 | 208 | } | |
596 | 209 | void Gesture::Cancel() { | 209 | } |
597 | 210 | while (!slices_.empty()) | 210 | |
598 | 211 | slices_.pop(); | 211 | uint64_t Gesture::Timeout() const { |
599 | 212 | last_slice_.reset(); | 212 | if (d_->recognized_) |
600 | 213 | return 0; | ||
601 | 214 | |||
602 | 215 | uint64_t time = 0; | ||
603 | 216 | if ((d_->subscription_->mask() & UGGestureTypeDrag) && | ||
604 | 217 | d_->subscription_->drag().timeout_ > time) | ||
605 | 218 | time = d_->subscription_->drag().timeout_; | ||
606 | 219 | if ((d_->subscription_->mask() & UGGestureTypePinch) && | ||
607 | 220 | d_->subscription_->pinch().timeout_ > time) | ||
608 | 221 | time = d_->subscription_->pinch().timeout_; | ||
609 | 222 | if ((d_->subscription_->mask() & UGGestureTypeRotate) && | ||
610 | 223 | d_->subscription_->rotate().timeout_ > time) | ||
611 | 224 | time = d_->subscription_->rotate().timeout_; | ||
612 | 225 | if ((d_->subscription_->mask() & UGGestureTypeTap) && | ||
613 | 226 | d_->subscription_->tap().timeout_ > time) | ||
614 | 227 | time = d_->subscription_->tap().timeout_; | ||
615 | 228 | |||
616 | 229 | return time; | ||
617 | 230 | } | ||
618 | 231 | |||
619 | 232 | float Gesture::AngleForTouch(unsigned int touch_id) const { | ||
620 | 233 | auto it = d_->angles_.find(touch_id); | ||
621 | 234 | if (it != d_->angles_.end()) | ||
622 | 235 | return it->second; | ||
623 | 236 | |||
624 | 237 | return 0; | ||
625 | 238 | } | ||
626 | 239 | |||
627 | 240 | void Gesture::SetAngleForTouch(unsigned int touch_id, float angle) { | ||
628 | 241 | d_->angles_[touch_id] = angle; | ||
629 | 242 | } | ||
630 | 243 | |||
631 | 244 | void Gesture::Cancel() { | ||
632 | 245 | while (!d_->slices_.empty()) | ||
633 | 246 | d_->slices_.pop(); | ||
634 | 247 | d_->last_slice_.reset(); | ||
635 | 248 | } | ||
636 | 249 | |||
637 | 250 | const unsigned int Gesture::id() const { | ||
638 | 251 | return d_->id_; | ||
639 | 252 | } | ||
640 | 253 | |||
641 | 254 | const Recognizer & Gesture::recognizer() const { | ||
642 | 255 | return *d_->recognizer_; | ||
643 | 256 | } | ||
644 | 257 | |||
645 | 258 | utouch::grail::UGSubscription* Gesture::subscription() const { | ||
646 | 259 | return d_->subscription_; | ||
647 | 260 | } | ||
648 | 261 | |||
649 | 262 | const TouchSet& Gesture::touches() const { | ||
650 | 263 | return d_->touches_; | ||
651 | 264 | } | ||
652 | 265 | |||
653 | 266 | const uint64_t Gesture::start_time() const { | ||
654 | 267 | return d_->start_time_; | ||
655 | 268 | } | ||
656 | 269 | |||
657 | 270 | bool Gesture::canceled() const { | ||
658 | 271 | return d_->canceled_; | ||
659 | 272 | } | ||
660 | 273 | |||
661 | 274 | bool Gesture::ended() const { | ||
662 | 275 | return d_->ended_; | ||
663 | 276 | } | ||
664 | 277 | } | ||
665 | 213 | } | 278 | } |
666 | 214 | 279 | ||
667 | === modified file 'src/v3/gesture.h' | |||
668 | --- src/v3/gesture.h 2011-10-20 22:19:11 +0000 | |||
669 | +++ src/v3/gesture.h 2011-11-01 21:20:40 +0000 | |||
670 | @@ -31,49 +31,46 @@ | |||
671 | 31 | 31 | ||
672 | 32 | #include "utouch/grail.h" | 32 | #include "utouch/grail.h" |
673 | 33 | 33 | ||
719 | 34 | class Recognizer; | 34 | namespace utouch { |
720 | 35 | class UGSlice_; | 35 | namespace grail { |
721 | 36 | 36 | class Recognizer; | |
722 | 37 | typedef std::shared_ptr<UGSlice_> SharedUGSlice_; | 37 | |
723 | 38 | typedef std::set<unsigned int> TouchSet; | 38 | class UGSubscription; |
724 | 39 | 39 | class UGSlice; | |
725 | 40 | class Gesture : public std::enable_shared_from_this<Gesture> { | 40 | typedef std::shared_ptr<UGSlice> SharedUGSlice; |
726 | 41 | public: | 41 | |
727 | 42 | Gesture(Recognizer* recognizer, UGSubscription_* subscription, | 42 | typedef std::set<unsigned int> TouchSet; |
728 | 43 | TouchSet& touches, uint64_t start_time); | 43 | |
729 | 44 | Gesture(const Gesture* gesture, TouchSet& touches); | 44 | class Gesture : public std::enable_shared_from_this<Gesture> { |
730 | 45 | 45 | public: | |
731 | 46 | void Update(UFEvent event, TouchSet& touches); | 46 | Gesture(Recognizer* recognizer, utouch::grail::UGSubscription* subscription, |
732 | 47 | bool IsOwned() const; | 47 | TouchSet& touches, uint64_t start_time); |
733 | 48 | void FlushSlices(); | 48 | Gesture(const Gesture* gesture, TouchSet& touches); |
734 | 49 | uint64_t Timeout() const; | 49 | |
735 | 50 | float AngleForTouch(unsigned int touch_id) const; | 50 | void Update(UFEvent event, TouchSet& touches); |
736 | 51 | void SetAngleForTouch(unsigned int touch_id, float angle); | 51 | bool IsOwned() const; |
737 | 52 | void Cancel(); | 52 | void FlushSlices(); |
738 | 53 | 53 | uint64_t Timeout() const; | |
739 | 54 | const unsigned int id() const { return id_; } | 54 | float AngleForTouch(unsigned int touch_id) const; |
740 | 55 | const Recognizer& recognizer() const { return *recognizer_; } | 55 | void SetAngleForTouch(unsigned int touch_id, float angle); |
741 | 56 | UGSubscription_* subscription() const { return subscription_; } | 56 | void Cancel(); |
742 | 57 | const TouchSet& touches() const { return touches_; } | 57 | |
743 | 58 | const uint64_t start_time() const { return start_time_; } | 58 | const unsigned int id() const; |
744 | 59 | bool canceled() const { return canceled_; } | 59 | const Recognizer& recognizer() const; |
745 | 60 | bool ended() const { return ended_; } | 60 | utouch::grail::UGSubscription* subscription() const; |
746 | 61 | 61 | const TouchSet& touches() const; | |
747 | 62 | Gesture(const Gesture&) = delete; | 62 | const uint64_t start_time() const; |
748 | 63 | void operator=(const Gesture&) = delete; | 63 | bool canceled() const; |
749 | 64 | 64 | bool ended() const; | |
750 | 65 | private: | 65 | |
751 | 66 | Recognizer* recognizer_; | 66 | Gesture(const Gesture&) = delete; |
752 | 67 | unsigned int id_; | 67 | void operator=(const Gesture&) = delete; |
753 | 68 | UGSubscription_* subscription_; | 68 | |
754 | 69 | TouchSet touches_; | 69 | private: |
755 | 70 | uint64_t start_time_; | 70 | struct Private; |
756 | 71 | UGGestureTypeMask recognized_; | 71 | std::shared_ptr< Private > d_; |
757 | 72 | std::queue<SharedUGSlice_> slices_; | 72 | }; |
758 | 73 | SharedUGSlice_ last_slice_; | 73 | |
759 | 74 | bool canceled_; | 74 | } |
760 | 75 | bool ended_; | 75 | } |
716 | 76 | std::map<unsigned int, float> angles_; | ||
717 | 77 | }; | ||
718 | 78 | |||
761 | 79 | #endif // UTOUCH_GRAIL_GESTURE_H_ | 76 | #endif // UTOUCH_GRAIL_GESTURE_H_ |
762 | 80 | 77 | ||
763 | === modified file 'src/v3/handle.cpp' | |||
764 | --- src/v3/handle.cpp 2011-10-19 22:06:43 +0000 | |||
765 | +++ src/v3/handle.cpp 2011-11-01 21:20:40 +0000 | |||
766 | @@ -21,9 +21,9 @@ | |||
767 | 21 | 21 | ||
768 | 22 | #include "v3/handle.h" | 22 | #include "v3/handle.h" |
769 | 23 | 23 | ||
773 | 24 | #include <assert.h> | 24 | #include <cassert> |
774 | 25 | #include <errno.h> | 25 | #include <cerrno> |
775 | 26 | #include <stdio.h> | 26 | #include <cstdio> |
776 | 27 | #include <sys/eventfd.h> | 27 | #include <sys/eventfd.h> |
777 | 28 | #include <unistd.h> | 28 | #include <unistd.h> |
778 | 29 | 29 | ||
779 | @@ -33,315 +33,347 @@ | |||
780 | 33 | 33 | ||
781 | 34 | #include "v3/event.h" | 34 | #include "v3/event.h" |
782 | 35 | #include "v3/recognizer.h" | 35 | #include "v3/recognizer.h" |
783 | 36 | #include "v3/slice.h" | ||
784 | 36 | #include "v3/subscription.h" | 37 | #include "v3/subscription.h" |
785 | 37 | 38 | ||
1096 | 38 | UGHandle_::UGHandle_(UFHandle frame_handle) | 39 | namespace utouch { |
1097 | 39 | : frame_handle_(frame_handle), | 40 | namespace grail { |
1098 | 40 | event_fd_(-1), | 41 | |
1099 | 41 | next_id_(0) { | 42 | struct UGHandle::Private { |
1100 | 42 | } | 43 | |
1101 | 43 | 44 | Private( UFHandle frame_handle ) | |
1102 | 44 | UGStatus UGHandle_::Initialize() { | 45 | : frame_handle_(frame_handle), |
1103 | 45 | event_fd_ = eventfd(0, EFD_NONBLOCK); | 46 | event_fd_(-1), |
1104 | 46 | if (event_fd_ == -1) { | 47 | next_id_(0) { |
1105 | 47 | fprintf(stderr, "Error: failed to create eventfd instance\n"); | 48 | } |
1106 | 48 | return UGStatusErrorResources; | 49 | |
1107 | 49 | } | 50 | typedef std::unique_ptr<Recognizer> UniqueRecognizer; |
1108 | 50 | 51 | ||
1109 | 51 | return UGStatusSuccess; | 52 | const UFHandle frame_handle_; |
1110 | 52 | } | 53 | int event_fd_; |
1111 | 53 | 54 | unsigned int next_id_; | |
1112 | 54 | UGHandle_* UGHandle_::NewUGHandle_(UFHandle frame_handle) { | 55 | std::map<UFDevice, std::map<Window, UniqueRecognizer>> recognizers_; |
1113 | 55 | UGHandle_* handle = new UGHandle_(frame_handle); | 56 | std::map<unsigned int, Recognizer*> gestures_; |
1114 | 56 | if (handle->Initialize() != UGStatusSuccess) { | 57 | std::list<utouch::grail::UGEvent*> event_queue_; |
1115 | 57 | delete handle; | 58 | |
1116 | 58 | return NULL; | 59 | UGStatus Initialize() { |
1117 | 59 | } | 60 | event_fd_ = eventfd(0, EFD_NONBLOCK); |
1118 | 60 | 61 | if (event_fd_ == -1) { | |
1119 | 61 | return handle; | 62 | fprintf(stderr, "Error: failed to create eventfd instance\n"); |
1120 | 62 | } | 63 | return UGStatusErrorResources; |
1121 | 63 | 64 | } | |
1122 | 64 | UGStatus UGHandle_::ActivateSubscription(UGSubscription_* subscription) { | 65 | |
1123 | 65 | Recognizer* recognizer; | 66 | return UGStatusSuccess; |
1124 | 66 | 67 | } | |
1125 | 67 | if (!subscription->IsValid()) | 68 | }; |
1126 | 68 | return UGStatusErrorInvalidSubscription; | 69 | |
1127 | 69 | 70 | ||
1128 | 70 | const auto& it = | 71 | UGHandle::UGHandle(UFHandle frame_handle) |
1129 | 71 | recognizers_[subscription->device()].find(subscription->window()); | 72 | : d_( new Private( frame_handle ) ) { |
1130 | 72 | if (it != recognizers_[subscription->device()].end()) { | 73 | } |
1131 | 73 | recognizer = it->second.get(); | 74 | |
1132 | 74 | } else { | 75 | int UGHandle::event_fd() const { |
1133 | 75 | recognizer = new Recognizer(this, subscription->device(), | 76 | return( d_->event_fd_ ); |
1134 | 76 | subscription->window()); | 77 | } |
1135 | 77 | recognizers_[subscription->device()][subscription->window()] = | 78 | |
1136 | 78 | std::move(UniqueRecognizer(recognizer)); | 79 | UGStatus UGHandle::ActivateSubscription( utouch::grail::UGSubscription * subscription) { |
1137 | 79 | } | 80 | Recognizer* recognizer; |
1138 | 80 | 81 | ||
1139 | 81 | recognizer->ActivateSubscription(subscription); | 82 | if (!subscription->IsValid()) |
1140 | 82 | 83 | return UGStatusErrorInvalidSubscription; | |
1141 | 83 | return UGStatusSuccess; | 84 | |
1142 | 84 | } | 85 | const auto& it = |
1143 | 85 | 86 | d_->recognizers_[subscription->device()].find(subscription->window()); | |
1144 | 86 | void UGHandle_::DeactivateSubscription(UGSubscription_* subscription) { | 87 | if (it != d_->recognizers_[subscription->device()].end()) { |
1145 | 87 | recognizers_[subscription->device()].erase(subscription->window()); | 88 | recognizer = it->second.get(); |
1146 | 88 | } | 89 | } else { |
1147 | 89 | 90 | recognizer = new Recognizer(this, subscription->device(), | |
1148 | 90 | namespace { | 91 | subscription->window()); |
1149 | 91 | 92 | d_->recognizers_[subscription->device()][subscription->window()] = | |
1150 | 92 | bool GetDeviceFromEvent(const UFEvent event, UFDevice* device) { | 93 | std::move( Private::UniqueRecognizer( recognizer ) ); |
1151 | 93 | UFStatus status = frame_event_get_property(event, UFEventPropertyDevice, | 94 | } |
1152 | 94 | device); | 95 | |
1153 | 95 | if (status != UFStatusSuccess) { | 96 | recognizer->ActivateSubscription( subscription ); |
1154 | 96 | fprintf(stderr, "Warning: failed to get device from event\n"); | 97 | |
1155 | 97 | return false; | 98 | return UGStatusSuccess; |
1156 | 98 | } | 99 | } |
1157 | 99 | 100 | ||
1158 | 100 | return true; | 101 | void UGHandle::DeactivateSubscription( utouch::grail::UGSubscription * subscription) { |
1159 | 101 | } | 102 | d_->recognizers_[subscription->device()].erase(subscription->window()); |
1160 | 102 | 103 | } | |
1161 | 103 | bool GetDeviceAndWindowFromEvent(const UFEvent event, UFDevice* device, | 104 | |
1162 | 104 | Window* window) { | 105 | namespace { |
1163 | 105 | UFFrame frame; | 106 | |
1164 | 106 | UFStatus status = frame_event_get_property(event, UFEventPropertyFrame, | 107 | bool GetDeviceFromEvent(const UFEvent event, UFDevice* device) { |
1165 | 107 | &frame); | 108 | UFStatus status = frame_event_get_property( event, |
1166 | 108 | if (status != UFStatusSuccess) { | 109 | UFEventPropertyDevice, |
1167 | 109 | fprintf(stderr, "Warning: failed to get frame from event\n"); | 110 | device); |
1168 | 110 | return false; | 111 | if (status != UFStatusSuccess) { |
1169 | 111 | } | 112 | fprintf(stderr, "Warning: failed to get device from event\n"); |
1170 | 112 | 113 | return false; | |
1171 | 113 | *device = frame_frame_get_device(frame); | 114 | } |
1172 | 114 | 115 | ||
1173 | 115 | status = frame_frame_get_property(frame, UFFramePropertyWindow, window); | 116 | return true; |
1174 | 116 | if (status != UFStatusSuccess) { | 117 | } |
1175 | 117 | fprintf(stderr, "Warning: failed to get window from frame\n"); | 118 | |
1176 | 118 | return false; | 119 | bool GetDeviceAndWindowFromEvent(const UFEvent event, UFDevice* device, |
1177 | 119 | } | 120 | Window* window) { |
1178 | 120 | 121 | UFFrame frame; | |
1179 | 121 | return true; | 122 | UFStatus status = frame_event_get_property(event, UFEventPropertyFrame, |
1180 | 122 | } | 123 | &frame); |
1181 | 123 | 124 | if (status != UFStatusSuccess) { | |
1182 | 124 | void RejectFrame(const UFEvent event, const UFDevice device, Window window) { | 125 | fprintf(stderr, "Warning: failed to get frame from event\n"); |
1183 | 125 | UFFrame frame; | 126 | return false; |
1184 | 126 | UFStatus status; | 127 | } |
1185 | 127 | unsigned int num_touches; | 128 | |
1186 | 128 | unsigned int i; | 129 | *device = frame_frame_get_device(frame); |
1187 | 129 | 130 | ||
1188 | 130 | status = frame_event_get_property(event, UFEventPropertyFrame, &frame); | 131 | status = frame_frame_get_property(frame, UFFramePropertyWindow, window); |
1189 | 131 | if (status != UFStatusSuccess) { | 132 | if (status != UFStatusSuccess) { |
1190 | 132 | fprintf(stderr, "Warning: failed to get frame from event\n"); | 133 | fprintf(stderr, "Warning: failed to get window from frame\n"); |
1191 | 133 | return; | 134 | return false; |
1192 | 134 | } | 135 | } |
1193 | 135 | 136 | ||
1194 | 136 | num_touches = frame_frame_get_num_touches(frame); | 137 | return true; |
1195 | 137 | 138 | } | |
1196 | 138 | for (i = 0; i < num_touches; ++i) { | 139 | |
1197 | 139 | UFTouch touch; | 140 | void RejectFrame(const UFEvent event, const UFDevice device, Window window) { |
1198 | 140 | unsigned int touch_id; | 141 | UFFrame frame; |
1199 | 141 | 142 | UFStatus status; | |
1200 | 142 | status = frame_frame_get_touch_by_index(frame, i, &touch); | 143 | unsigned int num_touches; |
1201 | 143 | if (status != UFStatusSuccess) { | 144 | unsigned int i; |
1202 | 144 | fprintf(stderr, "Warning: failed to get touch from frame by index\n"); | 145 | |
1203 | 145 | continue; | 146 | status = frame_event_get_property(event, UFEventPropertyFrame, &frame); |
1204 | 146 | } | 147 | if (status != UFStatusSuccess) { |
1205 | 147 | 148 | fprintf(stderr, "Warning: failed to get frame from event\n"); | |
1206 | 148 | if (frame_touch_get_state(touch) != UFTouchStateBegin) | 149 | return; |
1207 | 149 | continue; | 150 | } |
1208 | 150 | 151 | ||
1209 | 151 | status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id); | 152 | num_touches = frame_frame_get_num_touches(frame); |
1210 | 152 | if (status != UFStatusSuccess) { | 153 | |
1211 | 153 | fprintf(stderr, "Warning: failed to get touch ID from touch\n"); | 154 | for (i = 0; i < num_touches; ++i) { |
1212 | 154 | continue; | 155 | UFTouch touch; |
1213 | 155 | } | 156 | unsigned int touch_id; |
1214 | 156 | 157 | ||
1215 | 157 | frame_x11_reject_touch(device, window, touch_id); | 158 | status = frame_frame_get_touch_by_index(frame, i, &touch); |
1216 | 158 | } | 159 | if (status != UFStatusSuccess) { |
1217 | 159 | } | 160 | fprintf(stderr, "Warning: failed to get touch from frame by index\n"); |
1218 | 160 | 161 | continue; | |
1219 | 161 | } // namespace | 162 | } |
1220 | 162 | 163 | ||
1221 | 163 | void UGHandle_::ProcessFrameEvent(const UFEvent event) { | 164 | if (frame_touch_get_state(touch) != UFTouchStateBegin) |
1222 | 164 | switch (frame_event_get_type(event)) { | 165 | continue; |
1223 | 165 | case UFEventTypeDeviceAdded: { | 166 | |
1224 | 166 | UFDevice device; | 167 | status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id); |
1225 | 167 | if (!GetDeviceFromEvent(event, &device)) | 168 | if (status != UFStatusSuccess) { |
1226 | 168 | return; | 169 | fprintf(stderr, "Warning: failed to get touch ID from touch\n"); |
1227 | 169 | recognizers_.insert(std::make_pair(device, | 170 | continue; |
1228 | 170 | std::map<Window, UniqueRecognizer>())); | 171 | } |
1229 | 171 | break; | 172 | |
1230 | 172 | } | 173 | frame_x11_reject_touch(device, window, touch_id); |
1231 | 173 | 174 | } | |
1232 | 174 | case UFEventTypeDeviceRemoved: { | 175 | } |
1233 | 175 | UFDevice device; | 176 | |
1234 | 176 | if (!GetDeviceFromEvent(event, &device)) | 177 | } // namespace |
1235 | 177 | return; | 178 | |
1236 | 178 | recognizers_.erase(device); | 179 | void UGHandle::ProcessFrameEvent(const UFEvent event) { |
1237 | 179 | break; | 180 | switch (frame_event_get_type(event)) { |
1238 | 180 | } | 181 | case UFEventTypeDeviceAdded: { |
1239 | 181 | 182 | UFDevice device; | |
1240 | 182 | case UFEventTypeFrame: { | 183 | if (!GetDeviceFromEvent(event, &device)) |
1241 | 183 | UFDevice device; | 184 | return; |
1242 | 184 | Window window; | 185 | d_->recognizers_.insert(std::make_pair(device, |
1243 | 185 | if (!GetDeviceAndWindowFromEvent(event, &device, &window)) | 186 | std::map<Window, Private::UniqueRecognizer>())); |
1244 | 186 | return; | 187 | break; |
1245 | 187 | 188 | } | |
1246 | 188 | if (recognizers_[device].find(window) != recognizers_[device].end()) | 189 | |
1247 | 189 | recognizers_[device][window]->ProcessFrameEvent(event); | 190 | case UFEventTypeDeviceRemoved: { |
1248 | 190 | else | 191 | UFDevice device; |
1249 | 191 | RejectFrame(event, device, window); | 192 | if (!GetDeviceFromEvent(event, &device)) |
1250 | 192 | 193 | return; | |
1251 | 193 | break; | 194 | d_->recognizers_.erase(device); |
1252 | 194 | } | 195 | break; |
1253 | 195 | } | 196 | } |
1254 | 196 | } | 197 | |
1255 | 197 | 198 | case UFEventTypeFrame: { | |
1256 | 198 | void UGHandle_::UpdateTime(uint64_t time) { | 199 | UFDevice device; |
1257 | 199 | for (auto& pair : recognizers_) | 200 | Window window; |
1258 | 200 | for (auto& pair2 : pair.second) | 201 | if (!GetDeviceAndWindowFromEvent(event, &device, &window)) |
1259 | 201 | pair2.second->UpdateTime(time); | 202 | return; |
1260 | 202 | } | 203 | |
1261 | 203 | 204 | if (d_->recognizers_[device].find(window) != d_->recognizers_[device].end()) | |
1262 | 204 | unsigned int UGHandle_::NewGestureID(Recognizer* recognizer) { | 205 | d_->recognizers_[device][window]->ProcessFrameEvent(event); |
1263 | 205 | unsigned int id = next_id_++; | 206 | else |
1264 | 206 | gestures_[id] = recognizer; | 207 | RejectFrame(event, device, window); |
1265 | 207 | return id; | 208 | |
1266 | 208 | } | 209 | break; |
1267 | 209 | 210 | } | |
1268 | 210 | void UGHandle_::EnqueueEvent(const UGEvent_* event) { | 211 | } |
1269 | 211 | static const uint64_t num = 1; | 212 | } |
1270 | 212 | 213 | ||
1271 | 213 | event_queue_.push_back(event); | 214 | void UGHandle::UpdateTime(uint64_t time) { |
1272 | 214 | if (write(event_fd_, &num, sizeof(num)) != sizeof(num)) | 215 | for (auto& pair : d_->recognizers_) |
1273 | 215 | fprintf(stderr, "Warning: failed to update eventfd instance\n"); | 216 | for (auto& pair2 : pair.second) |
1274 | 216 | } | 217 | pair2.second->UpdateTime(time); |
1275 | 217 | 218 | } | |
1276 | 218 | void UGHandle_::RemoveGestureFromEventQueue(unsigned int id) { | 219 | |
1277 | 219 | for (auto it = event_queue_.begin(); it != event_queue_.end(); ) { | 220 | unsigned int UGHandle::NewGestureID(Recognizer* recognizer) { |
1278 | 220 | const UGEvent_* event = *it++; | 221 | unsigned int id = d_->next_id_++; |
1279 | 221 | if (grail_event_get_type(event) != UGEventTypeSlice) | 222 | d_->gestures_[id] = recognizer; |
1280 | 222 | continue; | 223 | return id; |
1281 | 223 | 224 | } | |
1282 | 224 | UGSlice slice; | 225 | |
1283 | 225 | UGStatus status = grail_event_get_property(event, UGEventPropertySlice, | 226 | void UGHandle::EnqueueEvent(utouch::grail::UGEvent * event) { |
1284 | 226 | &slice); | 227 | static const uint64_t num = 1; |
1285 | 227 | assert(status == UGStatusSuccess); | 228 | |
1286 | 228 | 229 | d_->event_queue_.push_back(event); | |
1287 | 229 | if (grail_slice_get_id(slice) == id) { | 230 | if (write(d_->event_fd_, &num, sizeof(num)) != sizeof(num)) |
1288 | 230 | event_queue_.remove(event); | 231 | fprintf(stderr, "Warning: failed to update eventfd instance\n"); |
1289 | 231 | ReleaseEvent(event); | 232 | } |
1290 | 232 | } | 233 | |
1291 | 233 | } | 234 | void UGHandle::RemoveGestureFromEventQueue(unsigned int id) { |
1292 | 234 | } | 235 | for (auto it = d_->event_queue_.begin(); it != d_->event_queue_.end(); ) { |
1293 | 235 | 236 | utouch::grail::UGEvent * event = *it++; | |
1294 | 236 | UGStatus UGHandle_::GetEvent(const UGEvent_** event) { | 237 | if (grail_event_get_type(event) != UGEventTypeSlice) |
1295 | 237 | /* Clear event fd (see eventfd(2) man page) */ | 238 | continue; |
1296 | 238 | uint64_t buf; | 239 | |
1297 | 239 | if (read(event_fd_, &buf, sizeof(buf)) != 8 && errno != EAGAIN) | 240 | void * slice; |
1298 | 240 | fprintf(stderr, "Warning: failed to read data from event fd\n"); | 241 | UGStatus status = grail_event_get_property( event, |
1299 | 241 | 242 | UGEventPropertySlice, | |
1300 | 242 | if (event_queue_.empty()) | 243 | &slice); |
1301 | 243 | return UGStatusErrorNoEvent; | 244 | assert(status == UGStatusSuccess); |
1302 | 244 | 245 | ||
1303 | 245 | *event = event_queue_.front(); | 246 | if (grail_slice_get_id(slice) == id) { |
1304 | 246 | event_queue_.pop_front(); | 247 | d_->event_queue_.remove(event); |
1305 | 247 | 248 | ReleaseEvent(event); | |
1306 | 248 | return UGStatusSuccess; | 249 | } |
1307 | 249 | } | 250 | } |
1308 | 250 | 251 | } | |
1309 | 251 | void UGHandle_::ReleaseEvent(const UGEvent_* event) { | 252 | |
1310 | 252 | delete event; | 253 | UGStatus UGHandle::GetEvent( const utouch::grail::UGEvent ** event) { |
1311 | 253 | } | 254 | /* Clear event fd (see eventfd(2) man page) */ |
1312 | 254 | 255 | uint64_t buf; | |
1313 | 255 | uint64_t UGHandle_::NextTimeout() const { | 256 | if( read(d_->event_fd_, &buf, sizeof(buf) ) != 8 && errno != EAGAIN) |
1314 | 256 | uint64_t min_timeout = std::numeric_limits<uint64_t>::max(); | 257 | fprintf(stderr, "Warning: failed to read data from event fd\n"); |
1315 | 257 | for (auto& pair : recognizers_) { | 258 | |
1316 | 258 | for (auto& pair2 : pair.second) { | 259 | if (d_->event_queue_.empty()) |
1317 | 259 | uint64_t timeout = pair2.second->NextTimeout(); | 260 | return UGStatusErrorNoEvent; |
1318 | 260 | if (timeout < min_timeout) | 261 | |
1319 | 261 | min_timeout = timeout; | 262 | *event = d_->event_queue_.front(); |
1320 | 262 | } | 263 | d_->event_queue_.pop_front(); |
1321 | 263 | } | 264 | |
1322 | 264 | 265 | return UGStatusSuccess; | |
1323 | 265 | return min_timeout != std::numeric_limits<uint64_t>::max() ? min_timeout : 0; | 266 | } |
1324 | 266 | } | 267 | |
1325 | 267 | 268 | void UGHandle::ReleaseEvent(const utouch::grail::UGEvent * event) { | |
1326 | 268 | UGStatus UGHandle_::AcceptGesture(unsigned int id) { | 269 | delete event; |
1327 | 269 | auto it = gestures_.find(id); | 270 | } |
1328 | 270 | if (it == gestures_.end()) | 271 | |
1329 | 271 | return UGStatusErrorInvalidGesture; | 272 | uint64_t UGHandle::NextTimeout() const { |
1330 | 272 | 273 | uint64_t min_timeout = std::numeric_limits<uint64_t>::max(); | |
1331 | 273 | return it->second->AcceptGesture(id); | 274 | for (auto& pair : d_->recognizers_) { |
1332 | 274 | } | 275 | for (auto& pair2 : pair.second) { |
1333 | 275 | 276 | uint64_t timeout = pair2.second->NextTimeout(); | |
1334 | 276 | UGStatus UGHandle_::RejectGesture(unsigned int id) { | 277 | if (timeout < min_timeout) |
1335 | 277 | auto it = gestures_.find(id); | 278 | min_timeout = timeout; |
1336 | 278 | if (it == gestures_.end()) | 279 | } |
1337 | 279 | return UGStatusErrorInvalidGesture; | 280 | } |
1338 | 280 | 281 | ||
1339 | 281 | return it->second->RejectGesture(id); | 282 | return min_timeout != std::numeric_limits<uint64_t>::max() ? min_timeout : 0; |
1340 | 282 | } | 283 | } |
1341 | 283 | 284 | ||
1342 | 284 | UGHandle_::~UGHandle_() { | 285 | UGStatus UGHandle::AcceptGesture(unsigned int id) { |
1343 | 285 | while (!event_queue_.empty()) { | 286 | auto it = d_->gestures_.find(id); |
1344 | 286 | ReleaseEvent(event_queue_.front()); | 287 | if (it == d_->gestures_.end()) |
1345 | 287 | event_queue_.pop_front(); | 288 | return UGStatusErrorInvalidGesture; |
1346 | 288 | } | 289 | |
1347 | 289 | } | 290 | return it->second->AcceptGesture(id); |
1348 | 290 | 291 | } | |
1349 | 291 | extern "C" { | 292 | |
1350 | 292 | 293 | UGStatus UGHandle::RejectGesture(unsigned int id) { | |
1351 | 293 | UGStatus grail_new(UFHandle frame_handle, UGHandle* handle) { | 294 | auto it = d_->gestures_.find(id); |
1352 | 294 | *handle = UGHandle_::NewUGHandle_(frame_handle); | 295 | if (it == d_->gestures_.end()) |
1353 | 295 | if (!*handle) | 296 | return UGStatusErrorInvalidGesture; |
1354 | 296 | return UGStatusErrorResources; | 297 | |
1355 | 297 | 298 | return it->second->RejectGesture(id); | |
1356 | 298 | return UGStatusSuccess; | 299 | } |
1357 | 299 | } | 300 | |
1358 | 300 | 301 | UGHandle::~UGHandle() { | |
1359 | 301 | void grail_delete_v3(UGHandle handle) { | 302 | while (!d_->event_queue_.empty()) { |
1360 | 302 | delete handle; | 303 | ReleaseEvent(d_->event_queue_.front()); |
1361 | 303 | } | 304 | d_->event_queue_.pop_front(); |
1362 | 304 | 305 | } | |
1363 | 305 | int grail_get_fd(UGHandle handle) { | 306 | } |
1364 | 306 | return handle->event_fd(); | 307 | } |
1365 | 307 | } | 308 | |
1366 | 308 | 309 | utouch::grail::UGHandle * utouch::grail::UGHandle::NewUGHandle( UFHandle frame_handle ) { | |
1367 | 309 | UGStatus grail_subscription_activate(UGHandle handle, | 310 | utouch::grail::UGHandle * handle = new utouch::grail::UGHandle(frame_handle); |
1368 | 310 | const UGSubscription subscription) { | 311 | if( handle->d_->Initialize() != UGStatusSuccess ) { |
1369 | 311 | return handle->ActivateSubscription(subscription); | 312 | delete handle; |
1370 | 312 | } | 313 | return NULL; |
1371 | 313 | 314 | } | |
1372 | 314 | void grail_subscription_deactivate(UGHandle handle, | 315 | |
1373 | 315 | const UGSubscription subscription) { | 316 | return handle; |
1374 | 316 | return handle->DeactivateSubscription(subscription); | 317 | } |
1375 | 317 | } | 318 | |
1376 | 318 | 319 | UGStatus grail_new(UFHandle frame_handle, UGHandle* handle) { | |
1377 | 319 | void grail_process_frame_event(UGHandle handle, const UFEvent event) { | 320 | assert( handle == NULL ); |
1378 | 320 | handle->ProcessFrameEvent(event); | 321 | *handle = utouch::grail::UGHandle::NewUGHandle(frame_handle); |
1379 | 321 | } | 322 | if (!*handle) |
1380 | 322 | 323 | return UGStatusErrorResources; | |
1381 | 323 | UGStatus grail_get_event(UGHandle handle, UGEvent *event) { | 324 | |
1382 | 324 | return handle->GetEvent(event); | 325 | return UGStatusSuccess; |
1383 | 325 | } | 326 | } |
1384 | 326 | 327 | ||
1385 | 327 | void grail_release_event(UGHandle handle, UGEvent event) { | 328 | void grail_delete_v3(UGHandle handle) { |
1386 | 328 | handle->ReleaseEvent(event); | 329 | assert( handle == NULL ); |
1387 | 329 | } | 330 | delete( static_cast< utouch::grail::UGHandle* >( handle ) ); |
1388 | 330 | 331 | } | |
1389 | 331 | void grail_update_time(UGHandle handle, uint64_t time) { | 332 | |
1390 | 332 | handle->UpdateTime(time); | 333 | int grail_get_fd(UGHandle handle) { |
1391 | 333 | } | 334 | assert( handle == NULL ); |
1392 | 334 | 335 | return static_cast< utouch::grail::UGHandle* >( handle )->event_fd(); | |
1393 | 335 | uint64_t grail_next_timeout(UGHandle handle) { | 336 | } |
1394 | 336 | return handle->NextTimeout(); | 337 | |
1395 | 337 | } | 338 | UGStatus grail_subscription_activate(UGHandle handle, |
1396 | 338 | 339 | const UGSubscription subscription) { | |
1397 | 339 | UGStatus grail_accept_gesture(UGHandle handle, unsigned int id) { | 340 | assert( handle == NULL ); |
1398 | 340 | return handle->AcceptGesture(id); | 341 | return static_cast< utouch::grail::UGHandle* >( handle )->ActivateSubscription(static_cast< utouch::grail::UGSubscription* >( subscription ) ); |
1399 | 341 | } | 342 | } |
1400 | 342 | 343 | ||
1401 | 343 | UGStatus grail_reject_gesture(UGHandle handle, unsigned int id) { | 344 | void grail_subscription_deactivate(UGHandle handle, |
1402 | 344 | return handle->RejectGesture(id); | 345 | const UGSubscription subscription) { |
1403 | 345 | } | 346 | assert( handle == NULL ); |
1404 | 346 | 347 | return static_cast< utouch::grail::UGHandle* >( handle )->DeactivateSubscription( static_cast< utouch::grail::UGSubscription* >( subscription ) ); | |
1405 | 347 | } // extern "C" | 348 | } |
1406 | 349 | |||
1407 | 350 | void grail_process_frame_event(UGHandle handle, const UFEvent event) { | ||
1408 | 351 | assert( handle == NULL ); | ||
1409 | 352 | static_cast< utouch::grail::UGHandle* >( handle )->ProcessFrameEvent( event ); | ||
1410 | 353 | } | ||
1411 | 354 | |||
1412 | 355 | UGStatus grail_get_event(UGHandle handle, UGEvent *event) { | ||
1413 | 356 | const utouch::grail::UGEvent * uge = static_cast< const utouch::grail::UGEvent* >( *event ); | ||
1414 | 357 | return static_cast< utouch::grail::UGHandle* >( handle )->GetEvent( &uge ); | ||
1415 | 358 | } | ||
1416 | 359 | |||
1417 | 360 | void grail_release_event(UGHandle handle, UGEvent event) { | ||
1418 | 361 | static_cast< utouch::grail::UGHandle* >( handle )->ReleaseEvent( static_cast< const utouch::grail::UGEvent* >( event ) ); | ||
1419 | 362 | } | ||
1420 | 363 | |||
1421 | 364 | void grail_update_time(UGHandle handle, uint64_t time) { | ||
1422 | 365 | static_cast< utouch::grail::UGHandle* >( handle )->UpdateTime(time); | ||
1423 | 366 | } | ||
1424 | 367 | |||
1425 | 368 | uint64_t grail_next_timeout(UGHandle handle) { | ||
1426 | 369 | return static_cast< utouch::grail::UGHandle* >( handle )->NextTimeout(); | ||
1427 | 370 | } | ||
1428 | 371 | |||
1429 | 372 | UGStatus grail_accept_gesture(UGHandle handle, unsigned int id) { | ||
1430 | 373 | return static_cast< utouch::grail::UGHandle* >( handle )->AcceptGesture(id); | ||
1431 | 374 | } | ||
1432 | 375 | |||
1433 | 376 | UGStatus grail_reject_gesture(UGHandle handle, unsigned int id) { | ||
1434 | 377 | return static_cast< utouch::grail::UGHandle* >( handle )->RejectGesture(id); | ||
1435 | 378 | } | ||
1436 | 379 | } | ||
1437 | 348 | 380 | ||
1438 | === modified file 'src/v3/handle.h' | |||
1439 | --- src/v3/handle.h 2011-10-18 21:35:48 +0000 | |||
1440 | +++ src/v3/handle.h 2011-11-01 21:20:40 +0000 | |||
1441 | @@ -31,44 +31,43 @@ | |||
1442 | 31 | 31 | ||
1443 | 32 | #include "utouch/grail.h" | 32 | #include "utouch/grail.h" |
1444 | 33 | 33 | ||
1485 | 34 | class Recognizer; | 34 | namespace utouch { |
1486 | 35 | class UGEvent_; | 35 | namespace grail { |
1487 | 36 | 36 | ||
1488 | 37 | class UGHandle_ { | 37 | class Recognizer; |
1489 | 38 | public: | 38 | |
1490 | 39 | static UGHandle_* NewUGHandle_(UFHandle frame_handle); | 39 | class UGEvent; |
1491 | 40 | 40 | class UGSubscription; | |
1492 | 41 | ~UGHandle_(); | 41 | |
1493 | 42 | 42 | class UGHandle { | |
1494 | 43 | int event_fd() const { return event_fd_; } | 43 | public: |
1495 | 44 | UGStatus ActivateSubscription(UGSubscription_* subscription); | 44 | static UGHandle* NewUGHandle(UFHandle frame_handle); |
1496 | 45 | void DeactivateSubscription(UGSubscription_* subscription); | 45 | |
1497 | 46 | unsigned int NewGestureID(Recognizer* recognizer); | 46 | ~UGHandle(); |
1498 | 47 | void ProcessFrameEvent(UFEvent event); | 47 | |
1499 | 48 | void UpdateTime(uint64_t time); | 48 | int event_fd() const; |
1500 | 49 | uint64_t NextTimeout() const; | 49 | UGStatus ActivateSubscription( utouch::grail::UGSubscription* subscription); |
1501 | 50 | void EnqueueEvent(const UGEvent_*); | 50 | void DeactivateSubscription( utouch::grail::UGSubscription* subscription); |
1502 | 51 | void RemoveGestureFromEventQueue(unsigned int id); | 51 | unsigned int NewGestureID(Recognizer* recognizer); |
1503 | 52 | UGStatus GetEvent(const UGEvent_** event); | 52 | void ProcessFrameEvent(UFEvent event); |
1504 | 53 | void ReleaseEvent(const UGEvent_* event); | 53 | void UpdateTime(uint64_t time); |
1505 | 54 | UGStatus AcceptGesture(unsigned int id); | 54 | uint64_t NextTimeout() const; |
1506 | 55 | UGStatus RejectGesture(unsigned int id); | 55 | void EnqueueEvent(utouch::grail::UGEvent * ); |
1507 | 56 | 56 | void RemoveGestureFromEventQueue(unsigned int id); | |
1508 | 57 | UGHandle_(const UGHandle_&) = delete; | 57 | UGStatus GetEvent( const utouch::grail::UGEvent ** event ); |
1509 | 58 | void operator=(const UGHandle_&) = delete; | 58 | void ReleaseEvent(const utouch::grail::UGEvent * event); |
1510 | 59 | 59 | UGStatus AcceptGesture(unsigned int id); | |
1511 | 60 | private: | 60 | UGStatus RejectGesture(unsigned int id); |
1512 | 61 | typedef std::unique_ptr<Recognizer> UniqueRecognizer; | 61 | |
1513 | 62 | 62 | UGHandle(const UGHandle&) = delete; | |
1514 | 63 | const UFHandle frame_handle_; | 63 | void operator=(const UGHandle&) = delete; |
1515 | 64 | int event_fd_; | 64 | |
1516 | 65 | unsigned int next_id_; | 65 | protected: |
1517 | 66 | std::map<UFDevice, std::map<Window, UniqueRecognizer>> recognizers_; | 66 | struct Private; |
1518 | 67 | std::map<unsigned int, Recognizer*> gestures_; | 67 | std::shared_ptr< Private > d_; |
1519 | 68 | std::list<const UGEvent_*> event_queue_; | 68 | |
1520 | 69 | 69 | UGHandle(UFHandle frame_handle); | |
1521 | 70 | UGHandle_(UFHandle frame_handle); | 70 | }; |
1522 | 71 | UGStatus Initialize(); | 71 | } |
1523 | 72 | }; | 72 | } |
1484 | 73 | |||
1524 | 74 | #endif // UTOUCH_GRAIL_HANDLE_H_ | 73 | #endif // UTOUCH_GRAIL_HANDLE_H_ |
1525 | 75 | 74 | ||
1526 | === modified file 'src/v3/recognizer.cpp' | |||
1527 | --- src/v3/recognizer.cpp 2011-10-19 22:07:30 +0000 | |||
1528 | +++ src/v3/recognizer.cpp 2011-11-01 21:20:40 +0000 | |||
1529 | @@ -21,8 +21,8 @@ | |||
1530 | 21 | 21 | ||
1531 | 22 | #include "v3/recognizer.h" | 22 | #include "v3/recognizer.h" |
1532 | 23 | 23 | ||
1535 | 24 | #include <stdint.h> | 24 | #include <cstdint> |
1536 | 25 | #include <stdio.h> | 25 | #include <cstdio> |
1537 | 26 | 26 | ||
1538 | 27 | #include <algorithm> | 27 | #include <algorithm> |
1539 | 28 | #include <limits> | 28 | #include <limits> |
1540 | @@ -35,492 +35,541 @@ | |||
1541 | 35 | 35 | ||
1542 | 36 | namespace { | 36 | namespace { |
1543 | 37 | 37 | ||
2032 | 38 | const uint64_t kCompositionTime = 60; | 38 | const uint64_t kCompositionTime = 60; |
2033 | 39 | 39 | ||
2034 | 40 | } // namespace | 40 | void GetModifiedAndEndedTouches(UFFrame frame, utouch::grail::TouchSet* modified, |
2035 | 41 | 41 | utouch::grail::TouchSet* ended, uint64_t event_time) { | |
2036 | 42 | Recognizer::Recognizer(UGHandle_* handle, const UFDevice device, Window window) | 42 | unsigned int num_touches = frame_frame_get_num_touches(frame); |
2037 | 43 | : handle_(handle), | 43 | for (unsigned int i = 0; i < num_touches; ++i) { |
2038 | 44 | device_(device), | 44 | UFTouch touch; |
2039 | 45 | window_(window), | 45 | UFStatus status = frame_frame_get_touch_by_index(frame, i, &touch); |
2040 | 46 | device_x_res_(46), /* Default to resolution of Apple Magic Trackpad */ | 46 | if (status != UFStatusSuccess) { |
2041 | 47 | device_y_res_(45), | 47 | fprintf(stderr, "Warning: failed to get touch from frame\n"); |
2042 | 48 | device_direct_(true) { | 48 | continue; |
2043 | 49 | UFAxis axis; | 49 | } |
2044 | 50 | UFStatus status = frame_device_get_axis_by_type(device, UFAxisTypeX, &axis); | 50 | |
2045 | 51 | if (status != UFStatusSuccess) | 51 | if (frame_touch_get_time(touch) == event_time) { |
2046 | 52 | fprintf(stderr, "Warning: failed to get X axis from device\n"); | 52 | unsigned int touch_id; |
2047 | 53 | else | 53 | status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id); |
2048 | 54 | device_x_res_ = frame_axis_get_resolution(axis); | 54 | if (status != UFStatusSuccess) { |
2049 | 55 | 55 | fprintf(stderr, "Warning: failed to get touch id from touch\n"); | |
2050 | 56 | status = frame_device_get_axis_by_type(device, UFAxisTypeY, &axis); | 56 | continue; |
2051 | 57 | if (status != UFStatusSuccess) | 57 | } |
2052 | 58 | fprintf(stderr, "Warning: failed to get Y axis from device\n"); | 58 | |
2053 | 59 | else | 59 | modified->insert(touch_id); |
2054 | 60 | device_y_res_ = frame_axis_get_resolution(axis); | 60 | |
2055 | 61 | 61 | if (frame_touch_get_state(touch) == UFTouchStateEnd) | |
2056 | 62 | status = frame_device_get_property(device, UFDevicePropertyDirect, | 62 | ended->insert(touch_id); |
2057 | 63 | &device_direct_); | 63 | } |
2058 | 64 | if (status != UFStatusSuccess) | 64 | } |
2059 | 65 | fprintf(stderr, | 65 | } |
2060 | 66 | "Warning: failed to get direct property value for device\n"); | 66 | |
2061 | 67 | } | 67 | } // namespace |
2062 | 68 | 68 | ||
2063 | 69 | void Recognizer::ActivateSubscription(UGSubscription_* subscription) { | 69 | namespace utouch { |
2064 | 70 | subscriptions_[subscription->touches_start() - 1].insert(subscription); | 70 | namespace grail { |
2065 | 71 | } | 71 | |
2066 | 72 | 72 | struct Recognizer::Private { | |
2067 | 73 | void Recognizer::DeactivateSubscription(UGSubscription_* subscription) { | 73 | |
2068 | 74 | subscriptions_[subscription->touches_start() - 1].erase(subscription); | 74 | Private( Recognizer * parent, utouch::grail::UGHandle * handle, const UFDevice device, Window window) |
2069 | 75 | 75 | : parent_( parent ), | |
2070 | 76 | for (auto it = unaccepted_gestures_.begin(); | 76 | handle_(handle), |
2071 | 77 | it != unaccepted_gestures_.end(); | 77 | device_(device), |
2072 | 78 | ) { | 78 | window_(window), |
2073 | 79 | const SharedGesture& gesture = *it++; | 79 | device_x_res_(46), /* Default to resolution of Apple Magic Trackpad */ |
2074 | 80 | if (gesture->subscription() == subscription) | 80 | device_y_res_(45), |
2075 | 81 | gesture->Cancel(); | 81 | device_direct_(true) { |
2076 | 82 | unaccepted_gestures_.erase(gesture); | 82 | UFAxis axis; |
2077 | 83 | } | 83 | UFStatus status = frame_device_get_axis_by_type(device, UFAxisTypeX, &axis); |
2078 | 84 | 84 | if (status != UFStatusSuccess) | |
2079 | 85 | for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) { | 85 | fprintf(stderr, "Warning: failed to get X axis from device\n"); |
2080 | 86 | const SharedGesture& gesture = *it++; | 86 | else |
2081 | 87 | if (gesture->subscription() == subscription) | 87 | device_x_res_ = frame_axis_get_resolution(axis); |
2082 | 88 | gesture->Cancel(); | 88 | |
2083 | 89 | accepted_gestures_.erase(gesture); | 89 | status = frame_device_get_axis_by_type(device, UFAxisTypeY, &axis); |
2084 | 90 | } | 90 | if (status != UFStatusSuccess) |
2085 | 91 | } | 91 | fprintf(stderr, "Warning: failed to get Y axis from device\n"); |
2086 | 92 | 92 | else | |
2087 | 93 | void Recognizer::ProcessFrameEvent(const UFEvent event) { | 93 | device_y_res_ = frame_axis_get_resolution(axis); |
2088 | 94 | UpdateTime(frame_event_get_time(event)); | 94 | |
2089 | 95 | MatchSubscriptionsForEvent(event); | 95 | status = frame_device_get_property( device, |
2090 | 96 | ProcessEvent(event); | 96 | UFDevicePropertyDirect, |
2091 | 97 | } | 97 | &device_direct_); |
2092 | 98 | 98 | if (status != UFStatusSuccess) | |
2093 | 99 | void Recognizer::MatchSubscriptionsForEvent(const UFEvent event) { | 99 | fprintf(stderr, |
2094 | 100 | bool active_subscriptions = false; | 100 | "Warning: failed to get direct property value for device\n"); |
2095 | 101 | for (auto subscriptions : subscriptions_) { | 101 | } |
2096 | 102 | if (!subscriptions.empty()) { | 102 | |
2097 | 103 | active_subscriptions = true; | 103 | void MatchSubscriptionsForEvent(const UFEvent event) { |
2098 | 104 | break; | 104 | bool active_subscriptions = false; |
2099 | 105 | } | 105 | for (auto subscriptions : subscriptions_) { |
2100 | 106 | } | 106 | if (!subscriptions.empty()) { |
2101 | 107 | if (!active_subscriptions) | 107 | active_subscriptions = true; |
2102 | 108 | return; | 108 | break; |
2103 | 109 | 109 | } | |
2104 | 110 | UFFrame frame; | 110 | } |
2105 | 111 | UFStatus status = frame_event_get_property(event, UFEventPropertyFrame, | 111 | if (!active_subscriptions) |
2106 | 112 | &frame); | 112 | return; |
2107 | 113 | if (status != UFStatusSuccess) { | 113 | |
2108 | 114 | fprintf(stderr, "Warning: failed to get frame from event\n"); | 114 | UFFrame frame; |
2109 | 115 | return; | 115 | UFStatus status = frame_event_get_property( event, |
2110 | 116 | } | 116 | UFEventPropertyFrame, |
2111 | 117 | 117 | &frame); | |
2112 | 118 | unsigned int num_touches = frame_frame_get_num_touches(frame); | 118 | if (status != UFStatusSuccess) { |
2113 | 119 | for (unsigned int i = 0; i < num_touches; ++i) { | 119 | fprintf(stderr, "Warning: failed to get frame from event\n"); |
2114 | 120 | UFTouch touch; | 120 | return; |
2115 | 121 | status = frame_frame_get_touch_by_index(frame, i, &touch); | 121 | } |
2116 | 122 | if (status != UFStatusSuccess) { | 122 | |
2117 | 123 | fprintf(stderr, "Warning: failed to get touch from frame\n"); | 123 | unsigned int num_touches = frame_frame_get_num_touches(frame); |
2118 | 124 | continue; | 124 | for (unsigned int i = 0; i < num_touches; ++i) { |
2119 | 125 | } | 125 | UFTouch touch; |
2120 | 126 | 126 | status = frame_frame_get_touch_by_index(frame, i, &touch); | |
2121 | 127 | unsigned int touch_id; | 127 | if (status != UFStatusSuccess) { |
2122 | 128 | status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id); | 128 | fprintf(stderr, "Warning: failed to get touch from frame\n"); |
2123 | 129 | if (status != UFStatusSuccess) { | 129 | continue; |
2124 | 130 | fprintf(stderr, "Warning: failed to get touch id from touch\n"); | 130 | } |
2125 | 131 | continue; | 131 | |
2126 | 132 | } | 132 | unsigned int touch_id; |
2127 | 133 | 133 | status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id); | |
2128 | 134 | switch (frame_touch_get_state(touch)) { | 134 | if (status != UFStatusSuccess) { |
2129 | 135 | case UFTouchStateBegin: { | 135 | fprintf(stderr, "Warning: failed to get touch id from touch\n"); |
2130 | 136 | start_times_[touch_id] = frame_touch_get_start_time(touch); | 136 | continue; |
2131 | 137 | unaccepted_touches_.insert(touch_id); | 137 | } |
2132 | 138 | free_touches_.insert(touch_id); | 138 | |
2133 | 139 | 139 | switch (frame_touch_get_state(touch)) { | |
2134 | 140 | for (const SharedGesture& gesture : accepted_gestures_) { | 140 | case UFTouchStateBegin: { |
2135 | 141 | UGSubscription_* subscription = gesture->subscription(); | 141 | start_times_[touch_id] = frame_touch_get_start_time(touch); |
2136 | 142 | if (gesture->touches().size() < subscription->touches_max()) { | 142 | unaccepted_touches_.insert(touch_id); |
2137 | 143 | TouchSet set(gesture->touches()); | 143 | free_touches_.insert(touch_id); |
2138 | 144 | set.insert(touch_id); | 144 | |
2139 | 145 | Gesture* new_gesture = new Gesture(gesture.get(), set); | 145 | for (const utouch::grail::SharedGesture & gesture : accepted_gestures_) { |
2140 | 146 | unaccepted_gestures_.insert(SharedGesture(new_gesture)); | 146 | utouch::grail::UGSubscription * subscription = gesture->subscription(); |
2141 | 147 | } | 147 | if (gesture->touches().size() < subscription->touches_max()) { |
2142 | 148 | } | 148 | TouchSet set(gesture->touches()); |
2143 | 149 | 149 | set.insert(touch_id); | |
2144 | 150 | for (const SharedGesture& gesture : unaccepted_gestures_) { | 150 | utouch::grail::Gesture* new_gesture = new utouch::grail::Gesture(gesture.get(), set); |
2145 | 151 | UGSubscription_* subscription = gesture->subscription(); | 151 | unaccepted_gestures_.insert(utouch::grail::SharedGesture(new_gesture)); |
2146 | 152 | if (gesture->touches().size() < subscription->touches_max()) { | 152 | } |
2147 | 153 | TouchSet set(gesture->touches()); | 153 | } |
2148 | 154 | set.insert(touch_id); | 154 | |
2149 | 155 | Gesture* new_gesture = new Gesture(gesture.get(), set); | 155 | for (const utouch::grail::SharedGesture & gesture : unaccepted_gestures_) { |
2150 | 156 | unaccepted_gestures_.insert(SharedGesture(new_gesture)); | 156 | utouch::grail::UGSubscription* subscription = gesture->subscription(); |
2151 | 157 | } | 157 | if (gesture->touches().size() < subscription->touches_max()) { |
2152 | 158 | } | 158 | TouchSet set(gesture->touches()); |
2153 | 159 | 159 | set.insert(touch_id); | |
2154 | 160 | MatchOneTouchGestures(touch_id); | 160 | utouch::grail::Gesture * new_gesture = new utouch::grail::Gesture(gesture.get(), set); |
2155 | 161 | MatchTwoTouchGestures(touch_id); | 161 | unaccepted_gestures_.insert( utouch::grail::SharedGesture(new_gesture)); |
2156 | 162 | MatchThreeTouchGestures(touch_id); | 162 | } |
2157 | 163 | MatchFourTouchGestures(touch_id); | 163 | } |
2158 | 164 | MatchFiveTouchGestures(touch_id); | 164 | |
2159 | 165 | break; | 165 | MatchOneTouchGestures(touch_id); |
2160 | 166 | } | 166 | MatchTwoTouchGestures(touch_id); |
2161 | 167 | 167 | MatchThreeTouchGestures(touch_id); | |
2162 | 168 | default: | 168 | MatchFourTouchGestures(touch_id); |
2163 | 169 | break; | 169 | MatchFiveTouchGestures(touch_id); |
2164 | 170 | } | 170 | break; |
2165 | 171 | } | 171 | } |
2166 | 172 | } | 172 | |
2167 | 173 | 173 | default: | |
2168 | 174 | void Recognizer::MatchOneTouchGestures(unsigned int touch_id) { | 174 | break; |
2169 | 175 | for (UGSubscription_* subscription : subscriptions_[0]) { | 175 | } |
2170 | 176 | TouchSet set; | 176 | } |
2171 | 177 | set.insert(touch_id); | 177 | } |
2172 | 178 | Gesture* gesture = new Gesture(this, subscription, set, | 178 | |
2173 | 179 | start_times_[touch_id]); | 179 | void MatchOneTouchGestures(unsigned int touch_id) { |
2174 | 180 | unaccepted_gestures_.insert(SharedGesture(gesture)); | 180 | for( utouch::grail::UGSubscription* subscription : subscriptions_[0] ) { |
2175 | 181 | } | 181 | TouchSet set; |
2176 | 182 | } | 182 | set.insert(touch_id); |
2177 | 183 | 183 | utouch::grail::Gesture* gesture = new utouch::grail::Gesture( parent_, | |
2178 | 184 | void Recognizer::MatchTwoTouchGestures(unsigned int touch_id) { | 184 | subscription, set, |
2179 | 185 | for (UGSubscription_* subscription : subscriptions_[1]) { | 185 | start_times_[touch_id]); |
2180 | 186 | for (unsigned int other_id : free_touches_) { | 186 | unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture)); |
2181 | 187 | if (other_id == touch_id) | 187 | } |
2182 | 188 | continue; | 188 | } |
2183 | 189 | 189 | ||
2184 | 190 | uint64_t min_start_time = start_times_[touch_id]; | 190 | void MatchTwoTouchGestures(unsigned int touch_id) { |
2185 | 191 | if (start_times_[other_id] < min_start_time && | 191 | for( utouch::grail::UGSubscription* subscription : subscriptions_[1] ) { |
2186 | 192 | unaccepted_touches_.find(other_id) != unaccepted_touches_.end()) | 192 | for (unsigned int other_id : free_touches_) { |
2187 | 193 | min_start_time = start_times_[other_id]; | 193 | if (other_id == touch_id) |
2188 | 194 | 194 | continue; | |
2189 | 195 | if (start_times_[touch_id] - min_start_time < kCompositionTime) { | 195 | |
2190 | 196 | TouchSet set; | 196 | uint64_t min_start_time = start_times_[touch_id]; |
2191 | 197 | set.insert(touch_id); | 197 | if (start_times_[other_id] < min_start_time && |
2192 | 198 | set.insert(other_id); | 198 | unaccepted_touches_.find(other_id) != unaccepted_touches_.end()) |
2193 | 199 | Gesture* gesture = new Gesture(this, subscription, set, | 199 | min_start_time = start_times_[other_id]; |
2194 | 200 | start_times_[touch_id]); | 200 | |
2195 | 201 | unaccepted_gestures_.insert(SharedGesture(gesture)); | 201 | if (start_times_[touch_id] - min_start_time < kCompositionTime) { |
2196 | 202 | } | 202 | TouchSet set; |
2197 | 203 | } | 203 | set.insert(touch_id); |
2198 | 204 | } | 204 | set.insert(other_id); |
2199 | 205 | } | 205 | utouch::grail::Gesture* gesture = new utouch::grail::Gesture(parent_, subscription, set, |
2200 | 206 | 206 | start_times_[touch_id]); | |
2201 | 207 | void Recognizer::MatchThreeTouchGestures(unsigned int touch_id) { | 207 | unaccepted_gestures_.insert( utouch::grail::SharedGesture(gesture) ); |
2202 | 208 | for (UGSubscription_* subscription : subscriptions_[2]) { | 208 | } |
2203 | 209 | for (unsigned int other_id_1 : free_touches_) { | 209 | } |
2204 | 210 | if (other_id_1 == touch_id) | 210 | } |
2205 | 211 | continue; | 211 | } |
2206 | 212 | 212 | ||
2207 | 213 | for (unsigned int other_id_2 : free_touches_) { | 213 | void MatchThreeTouchGestures(unsigned int touch_id) { |
2208 | 214 | if (other_id_2 == touch_id || other_id_2 == other_id_1) | 214 | for( utouch::grail::UGSubscription* subscription : subscriptions_[2] ) { |
2209 | 215 | continue; | 215 | for (unsigned int other_id_1 : free_touches_) { |
2210 | 216 | 216 | if (other_id_1 == touch_id) | |
2211 | 217 | uint64_t min_start_time = start_times_[touch_id]; | 217 | continue; |
2212 | 218 | if (start_times_[other_id_1] < min_start_time && | 218 | |
2213 | 219 | unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end()) | 219 | for (unsigned int other_id_2 : free_touches_) { |
2214 | 220 | min_start_time = start_times_[other_id_1]; | 220 | if (other_id_2 == touch_id || other_id_2 == other_id_1) |
2215 | 221 | if (start_times_[other_id_2] < min_start_time && | 221 | continue; |
2216 | 222 | unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end()) | 222 | |
2217 | 223 | min_start_time = start_times_[other_id_2]; | 223 | uint64_t min_start_time = start_times_[touch_id]; |
2218 | 224 | 224 | if (start_times_[other_id_1] < min_start_time && | |
2219 | 225 | if (start_times_[touch_id] - min_start_time < kCompositionTime) { | 225 | unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end()) |
2220 | 226 | TouchSet set; | 226 | min_start_time = start_times_[other_id_1]; |
2221 | 227 | set.insert(touch_id); | 227 | if (start_times_[other_id_2] < min_start_time && |
2222 | 228 | set.insert(other_id_1); | 228 | unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end()) |
2223 | 229 | set.insert(other_id_2); | 229 | min_start_time = start_times_[other_id_2]; |
2224 | 230 | Gesture* gesture = new Gesture(this, subscription, set, | 230 | |
2225 | 231 | start_times_[touch_id]); | 231 | if (start_times_[touch_id] - min_start_time < kCompositionTime) { |
2226 | 232 | unaccepted_gestures_.insert(SharedGesture(gesture)); | 232 | TouchSet set; |
2227 | 233 | } | 233 | set.insert(touch_id); |
2228 | 234 | } | 234 | set.insert(other_id_1); |
2229 | 235 | } | 235 | set.insert(other_id_2); |
2230 | 236 | } | 236 | utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_, subscription, set, |
2231 | 237 | } | 237 | start_times_[touch_id]); |
2232 | 238 | 238 | unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture)); | |
2233 | 239 | void Recognizer::MatchFourTouchGestures(unsigned int touch_id) { | 239 | } |
2234 | 240 | for (UGSubscription_* subscription : subscriptions_[3]) { | 240 | } |
2235 | 241 | for (unsigned int other_id_1 : free_touches_) { | 241 | } |
2236 | 242 | if (other_id_1 == touch_id) | 242 | } |
2237 | 243 | continue; | 243 | } |
2238 | 244 | 244 | ||
2239 | 245 | for (unsigned int other_id_2 : free_touches_) { | 245 | void MatchFourTouchGestures(unsigned int touch_id) { |
2240 | 246 | if (other_id_2 == touch_id || other_id_2 == other_id_1) | 246 | for( utouch::grail::UGSubscription* subscription : subscriptions_[3] ) { |
2241 | 247 | continue; | 247 | for (unsigned int other_id_1 : free_touches_) { |
2242 | 248 | 248 | if (other_id_1 == touch_id) | |
2243 | 249 | for (unsigned int other_id_3 : free_touches_) { | 249 | continue; |
2244 | 250 | if (other_id_3 == touch_id || other_id_3 == other_id_1 || | 250 | |
2245 | 251 | other_id_3 == other_id_2) | 251 | for (unsigned int other_id_2 : free_touches_) { |
2246 | 252 | continue; | 252 | if (other_id_2 == touch_id || other_id_2 == other_id_1) |
2247 | 253 | 253 | continue; | |
2248 | 254 | uint64_t min_start_time = start_times_[touch_id]; | 254 | |
2249 | 255 | if (start_times_[other_id_1] < min_start_time && | 255 | for (unsigned int other_id_3 : free_touches_) { |
2250 | 256 | unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end()) | 256 | if (other_id_3 == touch_id || other_id_3 == other_id_1 || |
2251 | 257 | min_start_time = start_times_[other_id_1]; | 257 | other_id_3 == other_id_2) |
2252 | 258 | if (start_times_[other_id_2] < min_start_time && | 258 | continue; |
2253 | 259 | unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end()) | 259 | |
2254 | 260 | min_start_time = start_times_[other_id_2]; | 260 | uint64_t min_start_time = start_times_[touch_id]; |
2255 | 261 | if (start_times_[other_id_3] < min_start_time && | 261 | if (start_times_[other_id_1] < min_start_time && |
2256 | 262 | unaccepted_touches_.find(other_id_3) != unaccepted_touches_.end()) | 262 | unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end()) |
2257 | 263 | min_start_time = start_times_[other_id_3]; | 263 | min_start_time = start_times_[other_id_1]; |
2258 | 264 | 264 | if (start_times_[other_id_2] < min_start_time && | |
2259 | 265 | if (start_times_[touch_id] - min_start_time < kCompositionTime) { | 265 | unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end()) |
2260 | 266 | TouchSet set; | 266 | min_start_time = start_times_[other_id_2]; |
2261 | 267 | set.insert(touch_id); | 267 | if (start_times_[other_id_3] < min_start_time && |
2262 | 268 | set.insert(other_id_1); | 268 | unaccepted_touches_.find(other_id_3) != unaccepted_touches_.end()) |
2263 | 269 | set.insert(other_id_2); | 269 | min_start_time = start_times_[other_id_3]; |
2264 | 270 | set.insert(other_id_3); | 270 | |
2265 | 271 | Gesture* gesture = new Gesture(this, subscription, set, | 271 | if (start_times_[touch_id] - min_start_time < kCompositionTime) { |
2266 | 272 | start_times_[touch_id]); | 272 | TouchSet set; |
2267 | 273 | unaccepted_gestures_.insert(SharedGesture(gesture)); | 273 | set.insert(touch_id); |
2268 | 274 | } | 274 | set.insert(other_id_1); |
2269 | 275 | } | 275 | set.insert(other_id_2); |
2270 | 276 | } | 276 | set.insert(other_id_3); |
2271 | 277 | } | 277 | utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_, |
2272 | 278 | } | 278 | subscription, |
2273 | 279 | } | 279 | set, |
2274 | 280 | 280 | start_times_[touch_id]); | |
2275 | 281 | void Recognizer::MatchFiveTouchGestures(unsigned int touch_id) { | 281 | unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture)); |
2276 | 282 | for (UGSubscription_* subscription : subscriptions_[4]) { | 282 | } |
2277 | 283 | for (unsigned int other_id_1 : free_touches_) { | 283 | } |
2278 | 284 | if (other_id_1 == touch_id) | 284 | } |
2279 | 285 | continue; | 285 | } |
2280 | 286 | 286 | } | |
2281 | 287 | for (unsigned int other_id_2 : free_touches_) { | 287 | } |
2282 | 288 | if (other_id_2 == touch_id || other_id_2 == other_id_1) | 288 | |
2283 | 289 | continue; | 289 | void MatchFiveTouchGestures(unsigned int touch_id) { |
2284 | 290 | 290 | for (utouch::grail::UGSubscription* subscription : subscriptions_[4]) { | |
2285 | 291 | for (unsigned int other_id_3 : free_touches_) { | 291 | for (unsigned int other_id_1 : free_touches_) { |
2286 | 292 | if (other_id_3 == touch_id || other_id_3 == other_id_1 || | 292 | if (other_id_1 == touch_id) |
2287 | 293 | other_id_3 == other_id_2) | 293 | continue; |
2288 | 294 | continue; | 294 | |
2289 | 295 | 295 | for (unsigned int other_id_2 : free_touches_) { | |
2290 | 296 | for (unsigned int other_id_4 : free_touches_) { | 296 | if (other_id_2 == touch_id || other_id_2 == other_id_1) |
2291 | 297 | if (other_id_4 == touch_id || other_id_4 == other_id_1 || | 297 | continue; |
2292 | 298 | other_id_4 == other_id_2 || other_id_4 == other_id_3) | 298 | |
2293 | 299 | continue; | 299 | for (unsigned int other_id_3 : free_touches_) { |
2294 | 300 | 300 | if (other_id_3 == touch_id || other_id_3 == other_id_1 || | |
2295 | 301 | uint64_t min_start_time = start_times_[touch_id]; | 301 | other_id_3 == other_id_2) |
2296 | 302 | if (start_times_[other_id_1] < min_start_time && | 302 | continue; |
2297 | 303 | unaccepted_touches_.find(other_id_1) != | 303 | |
2298 | 304 | unaccepted_touches_.end()) | 304 | for (unsigned int other_id_4 : free_touches_) { |
2299 | 305 | min_start_time = start_times_[other_id_1]; | 305 | if (other_id_4 == touch_id || other_id_4 == other_id_1 || |
2300 | 306 | if (start_times_[other_id_2] < min_start_time && | 306 | other_id_4 == other_id_2 || other_id_4 == other_id_3) |
2301 | 307 | unaccepted_touches_.find(other_id_2) != | 307 | continue; |
2302 | 308 | unaccepted_touches_.end()) | 308 | |
2303 | 309 | min_start_time = start_times_[other_id_2]; | 309 | uint64_t min_start_time = start_times_[touch_id]; |
2304 | 310 | if (start_times_[other_id_3] < min_start_time && | 310 | if (start_times_[other_id_1] < min_start_time && |
2305 | 311 | unaccepted_touches_.find(other_id_3) != | 311 | unaccepted_touches_.find(other_id_1) != |
2306 | 312 | unaccepted_touches_.end()) | 312 | unaccepted_touches_.end()) |
2307 | 313 | min_start_time = start_times_[other_id_3]; | 313 | min_start_time = start_times_[other_id_1]; |
2308 | 314 | if (start_times_[other_id_4] < min_start_time && | 314 | if (start_times_[other_id_2] < min_start_time && |
2309 | 315 | unaccepted_touches_.find(other_id_4) != | 315 | unaccepted_touches_.find(other_id_2) != |
2310 | 316 | unaccepted_touches_.end()) | 316 | unaccepted_touches_.end()) |
2311 | 317 | min_start_time = start_times_[other_id_4]; | 317 | min_start_time = start_times_[other_id_2]; |
2312 | 318 | 318 | if (start_times_[other_id_3] < min_start_time && | |
2313 | 319 | if (start_times_[touch_id] - min_start_time < kCompositionTime) { | 319 | unaccepted_touches_.find(other_id_3) != |
2314 | 320 | TouchSet set; | 320 | unaccepted_touches_.end()) |
2315 | 321 | set.insert(touch_id); | 321 | min_start_time = start_times_[other_id_3]; |
2316 | 322 | set.insert(other_id_1); | 322 | if (start_times_[other_id_4] < min_start_time && |
2317 | 323 | set.insert(other_id_2); | 323 | unaccepted_touches_.find(other_id_4) != |
2318 | 324 | set.insert(other_id_3); | 324 | unaccepted_touches_.end()) |
2319 | 325 | set.insert(other_id_4); | 325 | min_start_time = start_times_[other_id_4]; |
2320 | 326 | Gesture* gesture = new Gesture(this, subscription, set, | 326 | |
2321 | 327 | start_times_[touch_id]); | 327 | if (start_times_[touch_id] - min_start_time < kCompositionTime) { |
2322 | 328 | unaccepted_gestures_.insert(SharedGesture(gesture)); | 328 | TouchSet set; |
2323 | 329 | } | 329 | set.insert(touch_id); |
2324 | 330 | } | 330 | set.insert(other_id_1); |
2325 | 331 | } | 331 | set.insert(other_id_2); |
2326 | 332 | } | 332 | set.insert(other_id_3); |
2327 | 333 | } | 333 | set.insert(other_id_4); |
2328 | 334 | } | 334 | utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_, subscription, set, |
2329 | 335 | } | 335 | start_times_[touch_id]); |
2330 | 336 | 336 | unaccepted_gestures_.insert( utouch::grail::SharedGesture(gesture) ); | |
2331 | 337 | namespace { | 337 | } |
2332 | 338 | 338 | } | |
2333 | 339 | void GetModifiedAndEndedTouches(UFFrame frame, TouchSet* modified, | 339 | } |
2334 | 340 | TouchSet* ended, uint64_t event_time) { | 340 | } |
2335 | 341 | unsigned int num_touches = frame_frame_get_num_touches(frame); | 341 | } |
2336 | 342 | for (unsigned int i = 0; i < num_touches; ++i) { | 342 | } |
2337 | 343 | UFTouch touch; | 343 | } |
2338 | 344 | UFStatus status = frame_frame_get_touch_by_index(frame, i, &touch); | 344 | |
2339 | 345 | if (status != UFStatusSuccess) { | 345 | void ProcessEvent(const UFEvent& event) { |
2340 | 346 | fprintf(stderr, "Warning: failed to get touch from frame\n"); | 346 | UFFrame frame; |
2341 | 347 | continue; | 347 | UFStatus status = frame_event_get_property(event, UFEventPropertyFrame, |
2342 | 348 | } | 348 | &frame); |
2343 | 349 | 349 | if (status != UFStatusSuccess) { | |
2344 | 350 | if (frame_touch_get_time(touch) == event_time) { | 350 | fprintf(stderr, "Warning: failed to get frame from event\n"); |
2345 | 351 | unsigned int touch_id; | 351 | return; |
2346 | 352 | status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id); | 352 | } |
2347 | 353 | if (status != UFStatusSuccess) { | 353 | |
2348 | 354 | fprintf(stderr, "Warning: failed to get touch id from touch\n"); | 354 | TouchSet modified_touches; |
2349 | 355 | continue; | 355 | TouchSet ended_touches; |
2350 | 356 | } | 356 | GetModifiedAndEndedTouches(frame, &modified_touches, |
2351 | 357 | 357 | &ended_touches, frame_event_get_time(event)); | |
2352 | 358 | modified->insert(touch_id); | 358 | |
2353 | 359 | 359 | for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) { | |
2354 | 360 | if (frame_touch_get_state(touch) == UFTouchStateEnd) | 360 | const utouch::grail::SharedGesture & gesture = *it++; |
2355 | 361 | ended->insert(touch_id); | 361 | gesture->Update(event, modified_touches); |
2356 | 362 | } | 362 | if (gesture->ended()) { |
2357 | 363 | } | 363 | for (unsigned int touch_id : gesture->touches()) |
2358 | 364 | } | 364 | free_touches_.insert(touch_id); |
2359 | 365 | 365 | accepted_gestures_.erase(gesture); | |
2360 | 366 | } // namespace | 366 | } |
2361 | 367 | 367 | } | |
2362 | 368 | void Recognizer::ProcessEvent(const UFEvent& event) { | 368 | |
2363 | 369 | UFFrame frame; | 369 | for (auto it = unaccepted_gestures_.begin(); |
2364 | 370 | UFStatus status = frame_event_get_property(event, UFEventPropertyFrame, | 370 | it != unaccepted_gestures_.end(); |
2365 | 371 | &frame); | 371 | ) { |
2366 | 372 | if (status != UFStatusSuccess) { | 372 | const utouch::grail::SharedGesture & gesture = *it++; |
2367 | 373 | fprintf(stderr, "Warning: failed to get frame from event\n"); | 373 | gesture->Update(event, modified_touches); |
2368 | 374 | return; | 374 | if (gesture->canceled()) |
2369 | 375 | } | 375 | RejectGesture(gesture); |
2370 | 376 | 376 | } | |
2371 | 377 | TouchSet modified_touches; | 377 | |
2372 | 378 | TouchSet ended_touches; | 378 | for (unsigned int touch_id : ended_touches) |
2373 | 379 | GetModifiedAndEndedTouches(frame, &modified_touches, | 379 | free_touches_.erase(touch_id); |
2374 | 380 | &ended_touches, frame_event_get_time(event)); | 380 | } |
2375 | 381 | 381 | ||
2376 | 382 | for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) { | 382 | |
2377 | 383 | const SharedGesture& gesture = *it++; | 383 | |
2378 | 384 | gesture->Update(event, modified_touches); | 384 | void RejectGesture(const utouch::grail::SharedGesture& gesture) { |
2379 | 385 | if (gesture->ended()) { | 385 | gesture->Cancel(); |
2380 | 386 | for (unsigned int touch_id : gesture->touches()) | 386 | handle_->RemoveGestureFromEventQueue(gesture->id()); |
2381 | 387 | free_touches_.insert(touch_id); | 387 | unaccepted_gestures_.erase(gesture); |
2382 | 388 | accepted_gestures_.erase(gesture); | 388 | } |
2383 | 389 | } | 389 | |
2384 | 390 | } | 390 | Recognizer * parent_; |
2385 | 391 | 391 | ||
2386 | 392 | for (auto it = unaccepted_gestures_.begin(); | 392 | utouch::grail::UGHandle * const handle_; |
2387 | 393 | it != unaccepted_gestures_.end(); | 393 | const UFDevice device_; |
2388 | 394 | ) { | 394 | const Window window_; |
2389 | 395 | const SharedGesture& gesture = *it++; | 395 | float device_x_res_; /* Units of pixel/mm */ |
2390 | 396 | gesture->Update(event, modified_touches); | 396 | float device_y_res_; |
2391 | 397 | if (gesture->canceled()) | 397 | bool device_direct_; |
2392 | 398 | RejectGesture(gesture); | 398 | std::set<utouch::grail::UGSubscription*> subscriptions_[5]; |
2393 | 399 | } | 399 | std::set<utouch::grail::SharedGesture> unaccepted_gestures_; |
2394 | 400 | 400 | std::set<utouch::grail::SharedGesture> accepted_gestures_; | |
2395 | 401 | for (unsigned int touch_id : ended_touches) | 401 | std::map<unsigned int, uint64_t> start_times_; |
2396 | 402 | free_touches_.erase(touch_id); | 402 | TouchSet unaccepted_touches_; |
2397 | 403 | } | 403 | TouchSet accepted_touches_; |
2398 | 404 | 404 | TouchSet free_touches_; | |
2399 | 405 | void Recognizer::UpdateTime(uint64_t time) { | 405 | |
2400 | 406 | for (auto it = unaccepted_gestures_.begin(); | 406 | }; |
2401 | 407 | it != unaccepted_gestures_.end(); | 407 | |
2402 | 408 | ) { | 408 | Recognizer::Recognizer( utouch::grail::UGHandle * handle, const UFDevice device, Window window) |
2403 | 409 | const SharedGesture& gesture = *it++; | 409 | : d_( new Private( this, handle, device, window ) ) { |
2404 | 410 | uint64_t timeout = gesture->Timeout(); | 410 | } |
2405 | 411 | if (timeout && time - gesture->start_time() > timeout) | 411 | |
2406 | 412 | RejectGesture(gesture); | 412 | void Recognizer::ActivateSubscription( utouch::grail::UGSubscription * subscription) { |
2407 | 413 | } | 413 | d_->subscriptions_[subscription->touches_start() - 1].insert(subscription); |
2408 | 414 | 414 | } | |
2409 | 415 | for (auto it = unaccepted_touches_.begin(); it | 415 | |
2410 | 416 | != unaccepted_touches_.end(); | 416 | void Recognizer::DeactivateSubscription( utouch::grail::UGSubscription * subscription) { |
2411 | 417 | ) { | 417 | d_->subscriptions_[subscription->touches_start() - 1].erase(subscription); |
2412 | 418 | unsigned int touch_id = *it++; | 418 | |
2413 | 419 | if (time - start_times_[touch_id] < kCompositionTime) | 419 | for (auto it = d_->unaccepted_gestures_.begin(); |
2414 | 420 | continue; | 420 | it != d_->unaccepted_gestures_.end(); |
2415 | 421 | 421 | ) { | |
2416 | 422 | for (const SharedGesture& gesture : unaccepted_gestures_) | 422 | const utouch::grail::SharedGesture & gesture = *it++; |
2417 | 423 | if (gesture->touches().find(touch_id) != gesture->touches().end()) | 423 | if (gesture->subscription() == subscription) |
2418 | 424 | goto next_touch; | 424 | gesture->Cancel(); |
2419 | 425 | 425 | d_->unaccepted_gestures_.erase(gesture); | |
2420 | 426 | frame_x11_reject_touch(device_, window_, touch_id); | 426 | } |
2421 | 427 | unaccepted_touches_.erase(touch_id); | 427 | |
2422 | 428 | free_touches_.erase(touch_id); | 428 | for (auto it = d_->accepted_gestures_.begin(); it != d_->accepted_gestures_.end(); ) { |
2423 | 429 | 429 | const utouch::grail::SharedGesture& gesture = *it++; | |
2424 | 430 | next_touch: ; | 430 | if (gesture->subscription() == subscription) |
2425 | 431 | } | 431 | gesture->Cancel(); |
2426 | 432 | } | 432 | d_->accepted_gestures_.erase(gesture); |
2427 | 433 | 433 | } | |
2428 | 434 | uint64_t Recognizer::NextTimeout() { | 434 | } |
2429 | 435 | uint64_t min_timeout = std::numeric_limits<uint64_t>::max(); | 435 | |
2430 | 436 | for (unsigned int touch_id : unaccepted_touches_) | 436 | void Recognizer::ProcessFrameEvent(const UFEvent event) { |
2431 | 437 | if (kCompositionTime + start_times_[touch_id] < min_timeout) | 437 | UpdateTime(frame_event_get_time(event)); |
2432 | 438 | min_timeout = start_times_[touch_id] + kCompositionTime; | 438 | d_->MatchSubscriptionsForEvent(event); |
2433 | 439 | 439 | d_->ProcessEvent(event); | |
2434 | 440 | for (const SharedGesture& gesture : unaccepted_gestures_) { | 440 | } |
2435 | 441 | uint64_t timeout = gesture->Timeout(); | 441 | |
2436 | 442 | if (timeout && gesture->start_time() + timeout < min_timeout) | 442 | void Recognizer::UpdateTime(uint64_t time) { |
2437 | 443 | min_timeout = gesture->start_time() + timeout; | 443 | for (auto it = d_->unaccepted_gestures_.begin(); |
2438 | 444 | } | 444 | it != d_->unaccepted_gestures_.end(); |
2439 | 445 | 445 | ) { | |
2440 | 446 | return min_timeout; | 446 | const utouch::grail::SharedGesture & gesture = *it++; |
2441 | 447 | } | 447 | uint64_t timeout = gesture->Timeout(); |
2442 | 448 | 448 | if (timeout && time - gesture->start_time() > timeout) | |
2443 | 449 | UGStatus Recognizer::AcceptGesture(unsigned int id) { | 449 | d_->RejectGesture(gesture); |
2444 | 450 | SharedGesture gesture; | 450 | } |
2445 | 451 | for (const SharedGesture& test_gesture : unaccepted_gestures_) { | 451 | |
2446 | 452 | if (test_gesture->id() == id) { | 452 | for (auto it = d_->unaccepted_touches_.begin(); it |
2447 | 453 | gesture = test_gesture; | 453 | != d_->unaccepted_touches_.end(); |
2448 | 454 | break; | 454 | ) { |
2449 | 455 | } | 455 | unsigned int touch_id = *it++; |
2450 | 456 | } | 456 | if (time - d_->start_times_[touch_id] < kCompositionTime) |
2451 | 457 | 457 | continue; | |
2452 | 458 | if (!gesture) | 458 | |
2453 | 459 | return UGStatusErrorInvalidGesture; | 459 | for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_) |
2454 | 460 | 460 | if (gesture->touches().find(touch_id) != gesture->touches().end()) | |
2455 | 461 | for (unsigned int touch_id : gesture->touches()) { | 461 | goto next_touch; |
2456 | 462 | if (accepted_touches_.find(touch_id) == accepted_touches_.end()) { | 462 | |
2457 | 463 | frame_x11_accept_touch(device_, window_, touch_id); | 463 | frame_x11_reject_touch(d_->device_, d_->window_, touch_id); |
2458 | 464 | accepted_touches_.insert(touch_id); | 464 | d_->unaccepted_touches_.erase(touch_id); |
2459 | 465 | unaccepted_touches_.erase(touch_id); | 465 | d_->free_touches_.erase(touch_id); |
2460 | 466 | } else { | 466 | |
2461 | 467 | for (auto it = accepted_gestures_.begin(); | 467 | next_touch: ; |
2462 | 468 | it != accepted_gestures_.end(); | 468 | } |
2463 | 469 | ) { | 469 | } |
2464 | 470 | const SharedGesture& other_gesture = *it++; | 470 | |
2465 | 471 | const TouchSet& other_touches = other_gesture->touches(); | 471 | uint64_t Recognizer::NextTimeout() { |
2466 | 472 | if (other_touches.find(touch_id) != other_touches.end()) { | 472 | uint64_t min_timeout = std::numeric_limits<uint64_t>::max(); |
2467 | 473 | gesture->Cancel(); | 473 | for (unsigned int touch_id : d_->unaccepted_touches_) |
2468 | 474 | handle_->RemoveGestureFromEventQueue(other_gesture->id()); | 474 | if (kCompositionTime + d_->start_times_[touch_id] < min_timeout) |
2469 | 475 | accepted_gestures_.erase(other_gesture); | 475 | min_timeout = d_->start_times_[touch_id] + kCompositionTime; |
2470 | 476 | } | 476 | |
2471 | 477 | } | 477 | for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_) { |
2472 | 478 | } | 478 | uint64_t timeout = gesture->Timeout(); |
2473 | 479 | 479 | if (timeout && gesture->start_time() + timeout < min_timeout) | |
2474 | 480 | free_touches_.erase(touch_id); | 480 | min_timeout = gesture->start_time() + timeout; |
2475 | 481 | } | 481 | } |
2476 | 482 | 482 | ||
2477 | 483 | for (auto it = unaccepted_gestures_.begin(); | 483 | return min_timeout; |
2478 | 484 | it != unaccepted_gestures_.end(); | 484 | } |
2479 | 485 | ) { | 485 | |
2480 | 486 | const SharedGesture& other_gesture = *it++; | 486 | UGStatus Recognizer::AcceptGesture(unsigned int id) { |
2481 | 487 | if (other_gesture == gesture) | 487 | utouch::grail::SharedGesture gesture; |
2482 | 488 | continue; | 488 | for (const utouch::grail::SharedGesture & test_gesture : d_->unaccepted_gestures_) { |
2483 | 489 | for (unsigned int touch_id : other_gesture->touches()) { | 489 | if (test_gesture->id() == id) { |
2484 | 490 | if (gesture->touches().find(touch_id) != gesture->touches().end()) { | 490 | gesture = test_gesture; |
2485 | 491 | RejectGesture(other_gesture); | 491 | break; |
2486 | 492 | break; | 492 | } |
2487 | 493 | } | 493 | } |
2488 | 494 | } | 494 | |
2489 | 495 | } | 495 | if (!gesture) |
2490 | 496 | 496 | return UGStatusErrorInvalidGesture; | |
2491 | 497 | accepted_gestures_.insert(gesture); | 497 | |
2492 | 498 | unaccepted_gestures_.erase(gesture); | 498 | for (unsigned int touch_id : gesture->touches()) { |
2493 | 499 | 499 | if (d_->accepted_touches_.find(touch_id) == d_->accepted_touches_.end()) { | |
2494 | 500 | return UGStatusSuccess; | 500 | frame_x11_accept_touch(d_->device_, d_->window_, touch_id); |
2495 | 501 | } | 501 | d_->accepted_touches_.insert(touch_id); |
2496 | 502 | 502 | d_->unaccepted_touches_.erase(touch_id); | |
2497 | 503 | UGStatus Recognizer::RejectGesture(unsigned int id) { | 503 | } else { |
2498 | 504 | for (const SharedGesture& gesture : unaccepted_gestures_) { | 504 | for (auto it = d_->accepted_gestures_.begin(); |
2499 | 505 | if (gesture->id() == id) { | 505 | it != d_->accepted_gestures_.end(); |
2500 | 506 | RejectGesture(gesture); | 506 | ) { |
2501 | 507 | return UGStatusSuccess; | 507 | const utouch::grail::SharedGesture & other_gesture = *it++; |
2502 | 508 | } | 508 | const TouchSet& other_touches = other_gesture->touches(); |
2503 | 509 | } | 509 | if (other_touches.find(touch_id) != other_touches.end()) { |
2504 | 510 | 510 | gesture->Cancel(); | |
2505 | 511 | return UGStatusErrorInvalidGesture; | 511 | d_->handle_->RemoveGestureFromEventQueue(other_gesture->id()); |
2506 | 512 | } | 512 | d_->accepted_gestures_.erase(other_gesture); |
2507 | 513 | 513 | } | |
2508 | 514 | void Recognizer::RejectGesture(const SharedGesture& gesture) { | 514 | } |
2509 | 515 | gesture->Cancel(); | 515 | } |
2510 | 516 | handle_->RemoveGestureFromEventQueue(gesture->id()); | 516 | |
2511 | 517 | unaccepted_gestures_.erase(gesture); | 517 | d_->free_touches_.erase(touch_id); |
2512 | 518 | } | 518 | } |
2513 | 519 | 519 | ||
2514 | 520 | Recognizer::~Recognizer() { | 520 | for (auto it = d_->unaccepted_gestures_.begin(); |
2515 | 521 | for (const SharedGesture& gesture : unaccepted_gestures_) | 521 | it != d_->unaccepted_gestures_.end(); |
2516 | 522 | gesture->Cancel(); | 522 | ) { |
2517 | 523 | 523 | const utouch::grail::SharedGesture & other_gesture = *it++; | |
2518 | 524 | for (const SharedGesture& gesture : accepted_gestures_) | 524 | if (other_gesture == gesture) |
2519 | 525 | gesture->Cancel(); | 525 | continue; |
2520 | 526 | for (unsigned int touch_id : other_gesture->touches()) { | ||
2521 | 527 | if (gesture->touches().find(touch_id) != gesture->touches().end()) { | ||
2522 | 528 | d_->RejectGesture(other_gesture); | ||
2523 | 529 | break; | ||
2524 | 530 | } | ||
2525 | 531 | } | ||
2526 | 532 | } | ||
2527 | 533 | |||
2528 | 534 | d_->accepted_gestures_.insert(gesture); | ||
2529 | 535 | d_->unaccepted_gestures_.erase(gesture); | ||
2530 | 536 | |||
2531 | 537 | return UGStatusSuccess; | ||
2532 | 538 | } | ||
2533 | 539 | |||
2534 | 540 | UGStatus Recognizer::RejectGesture(unsigned int id) { | ||
2535 | 541 | for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_) { | ||
2536 | 542 | if (gesture->id() == id) { | ||
2537 | 543 | d_->RejectGesture(gesture); | ||
2538 | 544 | return UGStatusSuccess; | ||
2539 | 545 | } | ||
2540 | 546 | } | ||
2541 | 547 | |||
2542 | 548 | return UGStatusErrorInvalidGesture; | ||
2543 | 549 | } | ||
2544 | 550 | |||
2545 | 551 | utouch::grail::UGHandle * Recognizer::handle() const { | ||
2546 | 552 | return d_->handle_; | ||
2547 | 553 | } | ||
2548 | 554 | |||
2549 | 555 | float Recognizer::device_x_res() const { | ||
2550 | 556 | return d_->device_x_res_; | ||
2551 | 557 | } | ||
2552 | 558 | |||
2553 | 559 | float Recognizer::device_y_res() const { | ||
2554 | 560 | return d_->device_y_res_; | ||
2555 | 561 | } | ||
2556 | 562 | |||
2557 | 563 | bool Recognizer::device_direct() const { | ||
2558 | 564 | return d_->device_direct_; | ||
2559 | 565 | } | ||
2560 | 566 | |||
2561 | 567 | Recognizer::~Recognizer() { | ||
2562 | 568 | for (const utouch::grail::SharedGesture& gesture : d_->unaccepted_gestures_) | ||
2563 | 569 | gesture->Cancel(); | ||
2564 | 570 | |||
2565 | 571 | for (const utouch::grail::SharedGesture& gesture : d_->accepted_gestures_) | ||
2566 | 572 | gesture->Cancel(); | ||
2567 | 573 | } | ||
2568 | 574 | } | ||
2569 | 526 | } | 575 | } |
2570 | 527 | 576 | ||
2571 | === modified file 'src/v3/recognizer.h' | |||
2572 | --- src/v3/recognizer.h 2011-10-19 22:07:30 +0000 | |||
2573 | +++ src/v3/recognizer.h 2011-11-01 21:20:40 +0000 | |||
2574 | @@ -32,57 +32,44 @@ | |||
2575 | 32 | #include "utouch/grail.h" | 32 | #include "utouch/grail.h" |
2576 | 33 | #include "v3/subscription.h" | 33 | #include "v3/subscription.h" |
2577 | 34 | 34 | ||
2631 | 35 | class Gesture; | 35 | namespace utouch { |
2632 | 36 | class UGHandle_; | 36 | namespace grail { |
2633 | 37 | 37 | ||
2634 | 38 | typedef std::set<unsigned int> TouchSet; | 38 | class UGHandle; |
2635 | 39 | typedef std::shared_ptr<Gesture> SharedGesture; | 39 | class UGSubscription; |
2636 | 40 | 40 | ||
2637 | 41 | class Recognizer { | 41 | class Gesture; |
2638 | 42 | public: | 42 | typedef std::shared_ptr<Gesture> SharedGesture; |
2639 | 43 | Recognizer(UGHandle_* handle, const UFDevice device, Window window); | 43 | |
2640 | 44 | ~Recognizer(); | 44 | typedef std::set<unsigned int> TouchSet; |
2641 | 45 | 45 | ||
2642 | 46 | void ActivateSubscription(UGSubscription_* subscription); | 46 | class Recognizer { |
2643 | 47 | void DeactivateSubscription(UGSubscription_* subscription); | 47 | public: |
2644 | 48 | void ProcessFrameEvent(const UFEvent event); | 48 | Recognizer( utouch::grail::UGHandle * handle, const UFDevice device, Window window); |
2645 | 49 | void UpdateTime(uint64_t time); | 49 | ~Recognizer(); |
2646 | 50 | uint64_t NextTimeout(); | 50 | |
2647 | 51 | UGStatus AcceptGesture(unsigned int id); | 51 | void ActivateSubscription( utouch::grail::UGSubscription * subscription ); |
2648 | 52 | UGStatus RejectGesture(unsigned int id); | 52 | void DeactivateSubscription( utouch::grail::UGSubscription* subscription); |
2649 | 53 | 53 | void ProcessFrameEvent(const UFEvent event); | |
2650 | 54 | UGHandle_* handle() const { return handle_; } | 54 | void UpdateTime(uint64_t time); |
2651 | 55 | float device_x_res() const { return device_x_res_; } | 55 | uint64_t NextTimeout(); |
2652 | 56 | float device_y_res() const { return device_y_res_; } | 56 | UGStatus AcceptGesture(unsigned int id); |
2653 | 57 | bool device_direct() const { return device_direct_; } | 57 | UGStatus RejectGesture(unsigned int id); |
2654 | 58 | 58 | ||
2655 | 59 | Recognizer(const Recognizer&) = delete; | 59 | utouch::grail::UGHandle * handle() const; |
2656 | 60 | void operator=(const Recognizer&) = delete; | 60 | float device_x_res() const; |
2657 | 61 | 61 | float device_y_res() const; | |
2658 | 62 | private: | 62 | bool device_direct() const; |
2659 | 63 | UGHandle_* const handle_; | 63 | |
2660 | 64 | const UFDevice device_; | 64 | Recognizer(const Recognizer&) = delete; |
2661 | 65 | const Window window_; | 65 | void operator=(const Recognizer&) = delete; |
2662 | 66 | float device_x_res_; /* Units of pixel/mm */ | 66 | |
2663 | 67 | float device_y_res_; | 67 | protected: |
2664 | 68 | bool device_direct_; | 68 | |
2665 | 69 | std::set<UGSubscription_*> subscriptions_[5]; | 69 | struct Private; |
2666 | 70 | std::set<SharedGesture> unaccepted_gestures_; | 70 | std::shared_ptr< Private > d_; |
2667 | 71 | std::set<SharedGesture> accepted_gestures_; | 71 | |
2668 | 72 | std::map<unsigned int, uint64_t> start_times_; | 72 | }; |
2669 | 73 | TouchSet unaccepted_touches_; | 73 | } |
2670 | 74 | TouchSet accepted_touches_; | 74 | } |
2618 | 75 | TouchSet free_touches_; | ||
2619 | 76 | |||
2620 | 77 | void MatchSubscriptionsForEvent(const UFEvent event); | ||
2621 | 78 | void MatchSubscriptionsForTouch(unsigned int touch_id); | ||
2622 | 79 | void MatchOneTouchGestures(unsigned int touch_id); | ||
2623 | 80 | void MatchTwoTouchGestures(unsigned int touch_id); | ||
2624 | 81 | void MatchThreeTouchGestures(unsigned int touch_id); | ||
2625 | 82 | void MatchFourTouchGestures(unsigned int touch_id); | ||
2626 | 83 | void MatchFiveTouchGestures(unsigned int touch_id); | ||
2627 | 84 | void ProcessEvent(const UFEvent& event); | ||
2628 | 85 | void RejectGesture(const SharedGesture& gesture); | ||
2629 | 86 | }; | ||
2630 | 87 | |||
2671 | 88 | #endif // UTOUCH_GRAIL_RECOGNIZER_H_ | 75 | #endif // UTOUCH_GRAIL_RECOGNIZER_H_ |
2672 | 89 | 76 | ||
2673 | === modified file 'src/v3/slice.cpp' | |||
2674 | --- src/v3/slice.cpp 2011-10-21 00:06:58 +0000 | |||
2675 | +++ src/v3/slice.cpp 2011-11-01 21:20:40 +0000 | |||
2676 | @@ -21,10 +21,10 @@ | |||
2677 | 21 | 21 | ||
2678 | 22 | #include "v3/slice.h" | 22 | #include "v3/slice.h" |
2679 | 23 | 23 | ||
2684 | 24 | #include <assert.h> | 24 | #include <cassert> |
2685 | 25 | #include <math.h> | 25 | #include <cmath> |
2686 | 26 | #include <stdio.h> | 26 | #include <cstdio> |
2687 | 27 | #include <string.h> | 27 | #include <cstring> |
2688 | 28 | 28 | ||
2689 | 29 | #include <utouch/frame.h> | 29 | #include <utouch/frame.h> |
2690 | 30 | 30 | ||
2691 | @@ -32,550 +32,687 @@ | |||
2692 | 32 | #include "v3/recognizer.h" | 32 | #include "v3/recognizer.h" |
2693 | 33 | #include "v3/subscription.h" | 33 | #include "v3/subscription.h" |
2694 | 34 | 34 | ||
3242 | 35 | namespace { | 35 | namespace utouch { |
3243 | 36 | 36 | namespace grail { | |
3244 | 37 | const UGTransform kIdentityTransform = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; | 37 | |
3245 | 38 | 38 | const UGTransform kIdentityTransform = { | |
3246 | 39 | } // namespace | 39 | { 1, 0, 0 }, |
3247 | 40 | 40 | { 0, 1, 0 }, | |
3248 | 41 | UGSlice_::UGSlice_(const SharedGesture& gesture, UFEvent event, | 41 | { 0, 0, 1 } |
3249 | 42 | const TouchSet& touches, UGGestureTypeMask recognized) | 42 | }; |
3250 | 43 | : gesture_(gesture), | 43 | |
3251 | 44 | event_(event), | 44 | struct UGSlice::Private { |
3252 | 45 | frame_(NULL), | 45 | |
3253 | 46 | touches_(touches), | 46 | Private( const SharedUGSlice & prev, |
3254 | 47 | time_(frame_event_get_time(event)), | 47 | UFEvent event, |
3255 | 48 | state_(UGGestureStateBegin), | 48 | const TouchSet & touches ) |
3256 | 49 | original_center_x_(0), | 49 | : gesture_(prev->d_->gesture_), |
3257 | 50 | original_center_y_(0), | 50 | event_(event ? : NULL), |
3258 | 51 | original_radius_(0), | 51 | frame_(NULL), |
3259 | 52 | original_angle_(0), | 52 | touches_(touches), |
3260 | 53 | radius_(0), | 53 | time_(frame_event_get_time(event)), |
3261 | 54 | angle_(0), | 54 | state_(UGGestureStateUpdate), |
3262 | 55 | center_of_rotation_x_(0), | 55 | original_center_x_(prev->d_->original_center_x_), |
3263 | 56 | center_of_rotation_y_(0), | 56 | original_center_y_(prev->d_->original_center_y_), |
3264 | 57 | recognized_(recognized), | 57 | original_radius_(prev->d_->original_radius_), |
3265 | 58 | touch_count_changed_(false) { | 58 | original_angle_(prev->d_->original_angle_), |
3266 | 59 | frame_event_ref(event); | 59 | radius_(prev->d_->radius_), |
3267 | 60 | 60 | angle_(prev->d_->angle_), | |
3268 | 61 | memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform)); | 61 | center_of_rotation_x_(0), |
3269 | 62 | memcpy(cumulative_transform_, kIdentityTransform, sizeof(kIdentityTransform)); | 62 | center_of_rotation_y_(0), |
3270 | 63 | } | 63 | recognized_(prev->d_->recognized_), |
3271 | 64 | 64 | touch_count_changed_(touches_.size() != prev->d_->touches_.size()) { | |
3272 | 65 | UGSlice_* UGSlice_::NewUGSlice_(const SharedGesture& gesture, UFEvent event, | 65 | |
3273 | 66 | const TouchSet& touches, | 66 | ::memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform)); |
3274 | 67 | UGGestureTypeMask recognized) { | 67 | |
3275 | 68 | UGSlice_* slice = new UGSlice_(gesture, event, touches, recognized); | 68 | if( touch_count_changed_ ) { |
3276 | 69 | 69 | ::memcpy( cumulative_transform_, | |
3277 | 70 | UFStatus status = frame_event_get_property(event, UFEventPropertyFrame, | 70 | kIdentityTransform, |
3278 | 71 | &slice->frame_); | 71 | sizeof( kIdentityTransform ) |
3279 | 72 | if (status != UFStatusSuccess) { | 72 | ); |
3280 | 73 | fprintf(stderr, "Warning: failed to get frame from event\n"); | 73 | original_radius_ = 0; |
3281 | 74 | delete slice; | 74 | original_angle_ = 0; |
3282 | 75 | return NULL; | 75 | } else { |
3283 | 76 | } | 76 | memcpy( cumulative_transform_, |
3284 | 77 | 77 | prev->d_->cumulative_transform_, | |
3285 | 78 | slice->GetValues(touches, &slice->original_center_x_, | 78 | sizeof(prev->d_->cumulative_transform_) |
3286 | 79 | &slice->original_center_y_, &slice->original_radius_, | 79 | ); |
3287 | 80 | &slice->original_angle_, true); | 80 | } |
3288 | 81 | slice->radius_ = slice->original_radius_; | 81 | |
3289 | 82 | slice->angle_ = slice->original_angle_; | 82 | if (event_) |
3290 | 83 | 83 | frame_event_ref(event_); | |
3291 | 84 | return slice; | 84 | } |
3292 | 85 | } | 85 | |
3293 | 86 | 86 | Private( const SharedGesture & gesture, | |
3294 | 87 | UGSlice_::UGSlice_(const SharedUGSlice_& prev, UFEvent event, | 87 | UFEvent event, |
3295 | 88 | const TouchSet& touches) | 88 | const TouchSet & touches, |
3296 | 89 | : gesture_(prev->gesture_), | 89 | UGGestureTypeMask recognized ) |
3297 | 90 | event_(event ? : NULL), | 90 | : gesture_(gesture), |
3298 | 91 | frame_(NULL), | 91 | event_(event), |
3299 | 92 | touches_(touches), | 92 | frame_(NULL), |
3300 | 93 | time_(frame_event_get_time(event)), | 93 | touches_(touches), |
3301 | 94 | state_(UGGestureStateUpdate), | 94 | time_(frame_event_get_time(event)), |
3302 | 95 | original_center_x_(prev->original_center_x_), | 95 | state_(UGGestureStateBegin), |
3303 | 96 | original_center_y_(prev->original_center_y_), | 96 | original_center_x_(0), |
3304 | 97 | original_radius_(prev->original_radius_), | 97 | original_center_y_(0), |
3305 | 98 | original_angle_(prev->original_angle_), | 98 | original_radius_(0), |
3306 | 99 | radius_(prev->radius_), | 99 | original_angle_(0), |
3307 | 100 | angle_(prev->angle_), | 100 | radius_(0), |
3308 | 101 | center_of_rotation_x_(0), | 101 | angle_(0), |
3309 | 102 | center_of_rotation_y_(0), | 102 | center_of_rotation_x_(0), |
3310 | 103 | recognized_(prev->recognized_), | 103 | center_of_rotation_y_(0), |
3311 | 104 | touch_count_changed_(touches_.size() != prev->touches_.size()) { | 104 | recognized_(recognized), |
3312 | 105 | memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform)); | 105 | touch_count_changed_(false) { |
3313 | 106 | 106 | ||
3314 | 107 | if (touch_count_changed_) { | 107 | frame_event_ref(event); |
3315 | 108 | memcpy(cumulative_transform_, kIdentityTransform, | 108 | |
3316 | 109 | sizeof(kIdentityTransform)); | 109 | memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform)); |
3317 | 110 | original_radius_ = 0; | 110 | memcpy(cumulative_transform_, kIdentityTransform, sizeof(kIdentityTransform)); |
3318 | 111 | original_angle_ = 0; | 111 | } |
3319 | 112 | } else { | 112 | |
3320 | 113 | memcpy(cumulative_transform_, prev->cumulative_transform_, | 113 | ~Private() { |
3321 | 114 | sizeof(prev->cumulative_transform_)); | 114 | frame_event_unref(event_); |
3322 | 115 | } | 115 | } |
3323 | 116 | 116 | ||
3324 | 117 | if (event_) | 117 | const std::weak_ptr<Gesture> gesture_; |
3325 | 118 | frame_event_ref(event_); | 118 | SharedGesture gesture_ref_; |
3326 | 119 | } | 119 | const UFEvent event_; |
3327 | 120 | 120 | UFFrame frame_; | |
3328 | 121 | UGSlice_* UGSlice_::NewUGSlice_(const SharedUGSlice_& prev, UFEvent event, | 121 | TouchSet touches_; |
3329 | 122 | const TouchSet& touches) { | 122 | uint64_t time_; |
3330 | 123 | UGSlice_* slice = new UGSlice_(prev, event, touches); | 123 | UGGestureState state_; |
3331 | 124 | 124 | float original_center_x_; | |
3332 | 125 | UFStatus status = frame_event_get_property(event, UFEventPropertyFrame, | 125 | float original_center_y_; |
3333 | 126 | &slice->frame_); | 126 | float original_radius_; |
3334 | 127 | if (status != UFStatusSuccess) { | 127 | float original_angle_; |
3335 | 128 | fprintf(stderr, "Warning: failed to get frame from event\n"); | 128 | float radius_; |
3336 | 129 | delete slice; | 129 | float angle_; |
3337 | 130 | return NULL; | 130 | float transform_[3][3]; |
3338 | 131 | } | 131 | float cumulative_transform_[3][3]; |
3339 | 132 | 132 | float center_of_rotation_x_; | |
3340 | 133 | if (slice->touch_count_changed_) { | 133 | float center_of_rotation_y_; |
3341 | 134 | slice->GetValues(touches, &slice->original_center_x_, | 134 | UGGestureTypeMask recognized_; |
3342 | 135 | &slice->original_center_y_, &slice->original_radius_, | 135 | bool touch_count_changed_; |
3343 | 136 | &slice->original_angle_, true); | 136 | |
3344 | 137 | slice->radius_ = slice->original_radius_; | 137 | void GetValues( const TouchSet & touches, |
3345 | 138 | slice->angle_ = slice->original_angle_; | 138 | float * x, |
3346 | 139 | } else { | 139 | float * y, |
3347 | 140 | slice->SetTransforms(); | 140 | float * radius, |
3348 | 141 | slice->SetCenterOfRotation(); | 141 | float* angle, |
3349 | 142 | slice->CheckGestureEnd(); | 142 | bool init |
3350 | 143 | } | 143 | ) { |
3351 | 144 | 144 | assert( x == NULL ); | |
3352 | 145 | return slice; | 145 | assert( y == NULL ); |
3353 | 146 | } | 146 | assert( radius == NULL ); |
3354 | 147 | 147 | assert( angle == NULL ); | |
3355 | 148 | void UGSlice_::GetValues(const TouchSet& touches, float* x, float* y, | 148 | |
3356 | 149 | float* radius, float* angle, bool init) { | 149 | *x = 0; |
3357 | 150 | *x = 0; | 150 | *y = 0; |
3358 | 151 | *y = 0; | 151 | |
3359 | 152 | 152 | for (unsigned int touch_id : touches) { | |
3360 | 153 | for (unsigned int touch_id : touches) { | 153 | UFTouch touch; |
3361 | 154 | UFTouch touch; | 154 | UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch); |
3362 | 155 | UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch); | 155 | if (status != UFStatusSuccess) { |
3363 | 156 | if (status != UFStatusSuccess) { | 156 | fprintf(stderr, "Warning: failed to get touch from frame\n"); |
3364 | 157 | fprintf(stderr, "Warning: failed to get touch from frame\n"); | 157 | continue; |
3365 | 158 | continue; | 158 | } |
3366 | 159 | } | 159 | |
3367 | 160 | 160 | if (gesture_.lock()->recognizer().device_direct()) { | |
3368 | 161 | if (gesture_.lock()->recognizer().device_direct()) { | 161 | *x += frame_touch_get_window_x(touch); |
3369 | 162 | *x += frame_touch_get_window_x(touch); | 162 | *y += frame_touch_get_window_y(touch); |
3370 | 163 | *y += frame_touch_get_window_y(touch); | 163 | } else { |
3371 | 164 | } else { | 164 | *x += frame_touch_get_device_x(touch); |
3372 | 165 | *x += frame_touch_get_device_x(touch); | 165 | *y += frame_touch_get_device_y(touch); |
3373 | 166 | *y += frame_touch_get_device_y(touch); | 166 | } |
3374 | 167 | } | 167 | } |
3375 | 168 | } | 168 | |
3376 | 169 | 169 | *x /= touches.size(); | |
3377 | 170 | *x /= touches.size(); | 170 | *y /= touches.size(); |
3378 | 171 | *y /= touches.size(); | 171 | |
3379 | 172 | 172 | if (touches.size() == 1) | |
3380 | 173 | if (touches.size() == 1) | 173 | return; |
3381 | 174 | return; | 174 | |
3382 | 175 | 175 | *radius = 0; | |
3383 | 176 | *radius = 0; | 176 | *angle = 0; |
3384 | 177 | *angle = 0; | 177 | int num_angles = 0; |
3385 | 178 | int num_angles = 0; | 178 | for (unsigned int touch_id : touches) { |
3386 | 179 | for (unsigned int touch_id : touches) { | 179 | UFTouch touch; |
3387 | 180 | UFTouch touch; | 180 | float cur_x; |
3388 | 181 | float cur_x; | 181 | float cur_y; |
3389 | 182 | float cur_y; | 182 | |
3390 | 183 | 183 | UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch); | |
3391 | 184 | UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch); | 184 | if (status != UFStatusSuccess) { |
3392 | 185 | if (status != UFStatusSuccess) { | 185 | fprintf(stderr, "Warning: failed to get touch from frame\n"); |
3393 | 186 | fprintf(stderr, "Warning: failed to get touch from frame\n"); | 186 | continue; |
3394 | 187 | continue; | 187 | } |
3395 | 188 | } | 188 | |
3396 | 189 | 189 | if (gesture_.lock()->recognizer().device_direct()) { | |
3397 | 190 | if (gesture_.lock()->recognizer().device_direct()) { | 190 | cur_x = frame_touch_get_window_x(touch); |
3398 | 191 | cur_x = frame_touch_get_window_x(touch); | 191 | cur_y = frame_touch_get_window_y(touch); |
3399 | 192 | cur_y = frame_touch_get_window_y(touch); | 192 | } else { |
3400 | 193 | } else { | 193 | cur_x = frame_touch_get_device_x(touch); |
3401 | 194 | cur_x = frame_touch_get_device_x(touch); | 194 | cur_y = frame_touch_get_device_y(touch); |
3402 | 195 | cur_y = frame_touch_get_device_y(touch); | 195 | } |
3403 | 196 | } | 196 | |
3404 | 197 | 197 | *radius += sqrtf((cur_x - *x) * (cur_x - *x) + (cur_y - *y) * (cur_y - *y)); | |
3405 | 198 | *radius += sqrtf((cur_x - *x) * (cur_x - *x) + (cur_y - *y) * (cur_y - *y)); | 198 | |
3406 | 199 | 199 | float new_angle = atan2f(cur_y - *y, cur_x - *x); | |
3407 | 200 | float new_angle = atan2f(cur_y - *y, cur_x - *x); | 200 | |
3408 | 201 | 201 | if (init) { | |
3409 | 202 | if (init) { | 202 | *angle += new_angle; |
3410 | 203 | *angle += new_angle; | 203 | num_angles++; |
3411 | 204 | num_angles++; | 204 | } else if (frame_touch_get_state(touch) != UFTouchStateBegin) { |
3412 | 205 | } else if (frame_touch_get_state(touch) != UFTouchStateBegin) { | 205 | float prev_angle = gesture_.lock()->AngleForTouch(touch_id); |
3413 | 206 | float prev_angle = gesture_.lock()->AngleForTouch(touch_id); | 206 | |
3414 | 207 | 207 | if (new_angle - prev_angle < -M_PI) | |
3415 | 208 | if (new_angle - prev_angle < -M_PI) | 208 | new_angle += 2 * M_PI; |
3416 | 209 | new_angle += 2 * M_PI; | 209 | else if (new_angle - prev_angle > M_PI) |
3417 | 210 | else if (new_angle - prev_angle > M_PI) | 210 | new_angle -= 2 * M_PI; |
3418 | 211 | new_angle -= 2 * M_PI; | 211 | |
3419 | 212 | 212 | *angle += new_angle - prev_angle; | |
3420 | 213 | *angle += new_angle - prev_angle; | 213 | num_angles++; |
3421 | 214 | num_angles++; | 214 | } |
3422 | 215 | } | 215 | |
3423 | 216 | 216 | gesture_.lock()->SetAngleForTouch(touch_id, new_angle); | |
3424 | 217 | gesture_.lock()->SetAngleForTouch(touch_id, new_angle); | 217 | } |
3425 | 218 | } | 218 | |
3426 | 219 | 219 | *radius /= touches.size(); | |
3427 | 220 | *radius /= touches.size(); | 220 | *angle /= num_angles; |
3428 | 221 | *angle /= num_angles; | 221 | if (!init) |
3429 | 222 | if (!init) | 222 | *angle += angle_; |
3430 | 223 | *angle += angle_; | 223 | } |
3431 | 224 | } | 224 | |
3432 | 225 | 225 | /** | |
3433 | 226 | void UGSlice_::SetTransforms() { | 226 | * Determine the center of rotation point. |
3434 | 227 | float center_x; | 227 | * |
3435 | 228 | float center_y; | 228 | * For any given point q that is transformed by a 2D affine transformation |
3436 | 229 | float new_radius = radius_; | 229 | * matrix T about anchor point P the new point q' may be determined by the |
3437 | 230 | float new_angle = angle_; | 230 | * following equation: |
3438 | 231 | GetValues(touches_, ¢er_x, ¢er_y, &new_radius, &new_angle, false); | 231 | * |
3439 | 232 | 232 | * q' = T * (q - P) + P | |
3440 | 233 | if (!touch_count_changed_) { | 233 | * |
3441 | 234 | float scale = radius_ ? new_radius / radius_ : 1; | 234 | * T and P are dependent, so we can modify one and find a new value for the |
3442 | 235 | 235 | * other. We will label the original T and P as T0 and P0, and the new values | |
3443 | 236 | transform_[0][0] = cosf(new_angle - angle_) * scale; | 236 | * will be labeled T1 and P1. We can find new values by solving the following |
3444 | 237 | transform_[0][1] = -sinf(new_angle - angle_) * scale; | 237 | * equation: |
3445 | 238 | transform_[0][2] = | 238 | * |
3446 | 239 | center_x - cumulative_transform_[0][2] - original_center_x_; | 239 | * q' = T0 * (q - P0) + P0 = T1 * (q - P1) + P1 |
3447 | 240 | transform_[1][0] = -transform_[0][1]; | 240 | * |
3448 | 241 | transform_[1][1] = transform_[0][0]; | 241 | * In the calculations below, we use variables for the scalar values |
3449 | 242 | transform_[1][2] = | 242 | * that make up T0, P0, T1, and P1: |
3450 | 243 | center_y - cumulative_transform_[1][2] - original_center_y_; | 243 | * |
3451 | 244 | 244 | * T0: [ a -b c ] P0: [ x0 ] T1: [ a -b 0 ] P1: [ x1 ] | |
3452 | 245 | scale = original_radius_ ? new_radius / original_radius_ : 1; | 245 | * [ b a d ] [ y0 ] [ b a 0 ] [ y1 ] |
3453 | 246 | 246 | * [ 0 0 1 ] [ 0 ] [ 0 0 1 ] [ 0 ] | |
3454 | 247 | cumulative_transform_[0][0] = cosf(new_angle - original_angle_) * scale; | 247 | * |
3455 | 248 | cumulative_transform_[0][1] = -sinf(new_angle - original_angle_) * scale; | 248 | * Note that rotation and scaling are independent of the anchor point, so a and |
3456 | 249 | cumulative_transform_[0][2] = center_x - original_center_x_; | 249 | * b are equivalent between the transformation matrices. |
3457 | 250 | cumulative_transform_[1][0] = -cumulative_transform_[0][1]; | 250 | * |
3458 | 251 | cumulative_transform_[1][1] = cumulative_transform_[0][0]; | 251 | * Since we know all the values of T0, P0, and T1, we can calculate the values |
3459 | 252 | cumulative_transform_[1][2] = center_y - original_center_y_; | 252 | * x1 and y1 in P1. |
3460 | 253 | } else { | 253 | */ |
3461 | 254 | original_radius_ += new_radius - radius_; | 254 | void SetCenterOfRotation() { |
3462 | 255 | original_angle_ += new_angle - angle_; | 255 | float a = transform_[0][0]; |
3463 | 256 | original_center_x_ += | 256 | float b = transform_[1][0]; |
3464 | 257 | center_x - (original_center_x_ + cumulative_transform_[0][2]); | 257 | float c = transform_[0][2]; |
3465 | 258 | original_center_y_ += | 258 | float d = transform_[0][2]; |
3466 | 259 | center_y - (original_center_y_ + cumulative_transform_[1][2]); | 259 | float x0 = original_center_x_ + cumulative_transform_[0][2]; |
3467 | 260 | } | 260 | float y0 = original_center_y_ + cumulative_transform_[1][2]; |
3468 | 261 | 261 | float x1; | |
3469 | 262 | radius_ = new_radius; | 262 | float y1; |
3470 | 263 | angle_ = new_angle; | 263 | |
3471 | 264 | } | 264 | float div = a*a - 2*a + b*b + 1; |
3472 | 265 | 265 | ||
3473 | 266 | /** | 266 | // TODO: Replace magic number here :-) |
3474 | 267 | * Determine the center of rotation point. | 267 | if( ::fabsf( div ) < 1e-5 ) |
3475 | 268 | * | 268 | return; |
3476 | 269 | * For any given point q that is transformed by a 2D affine transformation | 269 | |
3477 | 270 | * matrix T about anchor point P the new point q' may be determined by the | 270 | x1 = (a*a*x0 - a*(2*x0+c) + b*b*x0 - b*d + c + x0) / div; |
3478 | 271 | * following equation: | 271 | y1 = (a*a*y0 - a*(2*y0+d) + b*b*y0 + b*c + d + y0) / div; |
3479 | 272 | * | 272 | |
3480 | 273 | * q' = T * (q - P) + P | 273 | center_of_rotation_x_ = x1; |
3481 | 274 | * | 274 | center_of_rotation_y_ = y1; |
3482 | 275 | * T and P are dependent, so we can modify one and find a new value for the | 275 | } |
3483 | 276 | * other. We will label the original T and P as T0 and P0, and the new values | 276 | |
3484 | 277 | * will be labeled T1 and P1. We can find new values by solving the following | 277 | void CheckGestureEnd() { |
3485 | 278 | * equation: | 278 | std::size_t num_active_touches = 0; |
3486 | 279 | * | 279 | |
3487 | 280 | * q' = T0 * (q - P0) + P0 = T1 * (q - P1) + P1 | 280 | for (unsigned int touch_id : touches_) { |
3488 | 281 | * | 281 | UFTouch touch; |
3489 | 282 | * In the calculations below, we use variables for the scalar values | 282 | UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch); |
3490 | 283 | * that make up T0, P0, T1, and P1: | 283 | if (status != UFStatusSuccess) { |
3491 | 284 | * | 284 | fprintf(stderr, "Warning: failed to get touch from frame by id\n"); |
3492 | 285 | * T0: [ a -b c ] P0: [ x0 ] T1: [ a -b 0 ] P1: [ x1 ] | 285 | continue; |
3493 | 286 | * [ b a d ] [ y0 ] [ b a 0 ] [ y1 ] | 286 | } |
3494 | 287 | * [ 0 0 1 ] [ 0 ] [ 0 0 1 ] [ 0 ] | 287 | |
3495 | 288 | * | 288 | if (frame_touch_get_state(touch) == UFTouchStateEnd) { |
3496 | 289 | * Note that rotation and scaling are independent of the anchor point, so a and | 289 | continue; |
3497 | 290 | * b are equivalent between the transformation matrices. | 290 | } else { |
3498 | 291 | * | 291 | int pending_end; |
3499 | 292 | * Since we know all the values of T0, P0, and T1, we can calculate the values | 292 | status = frame_touch_get_property(touch, UFTouchPropertyPendingEnd, |
3500 | 293 | * x1 and y1 in P1. | 293 | &pending_end); |
3501 | 294 | */ | 294 | if (status != UFStatusSuccess) { |
3502 | 295 | void UGSlice_::SetCenterOfRotation() { | 295 | fprintf(stderr, "Warning: failed to get touch pending end property\n"); |
3503 | 296 | float a = transform_[0][0]; | 296 | continue; |
3504 | 297 | float b = transform_[1][0]; | 297 | } |
3505 | 298 | float c = transform_[0][2]; | 298 | |
3506 | 299 | float d = transform_[0][2]; | 299 | if (pending_end) |
3507 | 300 | float x0 = original_center_x_ + cumulative_transform_[0][2]; | 300 | continue; |
3508 | 301 | float y0 = original_center_y_ + cumulative_transform_[1][2]; | 301 | } |
3509 | 302 | float x1; | 302 | |
3510 | 303 | float y1; | 303 | num_active_touches++; |
3511 | 304 | 304 | } | |
3512 | 305 | float div = a*a - 2*a + b*b + 1; | 305 | |
3513 | 306 | 306 | const UGSubscription * subscription = gesture_.lock()->subscription(); | |
3514 | 307 | if (fabsf(div) < 1e-5) | 307 | unsigned int touches_start = subscription->touches_start(); |
3515 | 308 | return; | 308 | unsigned int touches_min = subscription->touches_min(); |
3516 | 309 | 309 | if ((!touches_min && num_active_touches < touches_start) || | |
3517 | 310 | x1 = (a*a*x0 - a*(2*x0+c) + b*b*x0 - b*d + c + x0) / div; | 310 | (touches_min && num_active_touches < touches_min)) |
3518 | 311 | y1 = (a*a*y0 - a*(2*y0+d) + b*b*y0 + b*c + d + y0) / div; | 311 | state_ = UGGestureStateEnd; |
3519 | 312 | 312 | } | |
3520 | 313 | center_of_rotation_x_ = x1; | 313 | |
3521 | 314 | center_of_rotation_y_ = y1; | 314 | void SetTransforms() { |
3522 | 315 | } | 315 | float center_x; |
3523 | 316 | 316 | float center_y; | |
3524 | 317 | void UGSlice_::CheckGestureEnd() { | 317 | float new_radius = radius_; |
3525 | 318 | unsigned int num_active_touches = 0; | 318 | float new_angle = angle_; |
3526 | 319 | for (unsigned int touch_id : touches_) { | 319 | GetValues( touches_, ¢er_x, ¢er_y, &new_radius, &new_angle, false); |
3527 | 320 | UFTouch touch; | 320 | |
3528 | 321 | UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch); | 321 | if (touch_count_changed_) { |
3529 | 322 | if (status != UFStatusSuccess) { | 322 | float scale = radius_ > 0 ? new_radius / radius_ : 1; |
3530 | 323 | fprintf(stderr, "Warning: failed to get touch from frame by id\n"); | 323 | |
3531 | 324 | continue; | 324 | transform_[0][0] = cosf(new_angle - angle_) * scale; |
3532 | 325 | } | 325 | transform_[0][1] = -sinf(new_angle - angle_) * scale; |
3533 | 326 | 326 | transform_[0][2] = | |
3534 | 327 | if (frame_touch_get_state(touch) == UFTouchStateEnd) { | 327 | center_x - cumulative_transform_[0][2] - original_center_x_; |
3535 | 328 | continue; | 328 | transform_[1][0] = -transform_[0][1]; |
3536 | 329 | } else { | 329 | transform_[1][1] = transform_[0][0]; |
3537 | 330 | int pending_end; | 330 | transform_[1][2] = |
3538 | 331 | status = frame_touch_get_property(touch, UFTouchPropertyPendingEnd, | 331 | center_y - cumulative_transform_[1][2] - original_center_y_; |
3539 | 332 | &pending_end); | 332 | |
3540 | 333 | if (status != UFStatusSuccess) { | 333 | scale = original_radius_ > 0 ? new_radius / original_radius_ : 1; |
3541 | 334 | fprintf(stderr, "Warning: failed to get touch pending end property\n"); | 334 | |
3542 | 335 | continue; | 335 | cumulative_transform_[0][0] = ::cosf( new_angle - original_angle_ ) * scale; |
3543 | 336 | } | 336 | cumulative_transform_[0][1] = -::sinf( new_angle - original_angle_ ) * scale; |
3544 | 337 | 337 | cumulative_transform_[0][2] = center_x - original_center_x_; | |
3545 | 338 | if (pending_end) | 338 | cumulative_transform_[1][0] = -cumulative_transform_[0][1]; |
3546 | 339 | continue; | 339 | cumulative_transform_[1][1] = cumulative_transform_[0][0]; |
3547 | 340 | } | 340 | cumulative_transform_[1][2] = center_y - original_center_y_; |
3548 | 341 | 341 | } else { | |
3549 | 342 | num_active_touches++; | 342 | original_radius_ += new_radius - radius_; |
3550 | 343 | } | 343 | original_angle_ += new_angle - angle_; |
3551 | 344 | 344 | original_center_x_ += | |
3552 | 345 | const UGSubscription_* subscription = gesture_.lock()->subscription(); | 345 | center_x - (original_center_x_ + cumulative_transform_[0][2]); |
3553 | 346 | unsigned int touches_start = subscription->touches_start(); | 346 | original_center_y_ += |
3554 | 347 | unsigned int touches_min = subscription->touches_min(); | 347 | center_y - (original_center_y_ + cumulative_transform_[1][2]); |
3555 | 348 | if ((!touches_min && num_active_touches < touches_start) || | 348 | } |
3556 | 349 | (touches_min && num_active_touches < touches_min)) | 349 | |
3557 | 350 | state_ = UGGestureStateEnd; | 350 | radius_ = new_radius; |
3558 | 351 | } | 351 | angle_ = new_angle; |
3559 | 352 | 352 | } | |
3560 | 353 | uint64_t UGSlice_::CumulativeTime() const { | 353 | |
3561 | 354 | return time_ - gesture_.lock()->start_time(); | 354 | uint64_t CumulativeTime() const { |
3562 | 355 | } | 355 | return( time_ - gesture_.lock()->start_time() ); |
3563 | 356 | 356 | } | |
3564 | 357 | float UGSlice_::CumulativeDrag2() const { | 357 | |
3565 | 358 | float res_x = gesture_.lock()->recognizer().device_x_res(); | 358 | float CumulativeDrag2() const { |
3566 | 359 | float res_y = gesture_.lock()->recognizer().device_y_res(); | 359 | float res_x = gesture_.lock()->recognizer().device_x_res(); |
3567 | 360 | 360 | float res_y = gesture_.lock()->recognizer().device_y_res(); | |
3568 | 361 | return fabsf(cumulative_transform_[0][2] / res_x * | 361 | |
3569 | 362 | cumulative_transform_[0][2] / res_x + | 362 | return fabsf(cumulative_transform_[0][2] / res_x * |
3570 | 363 | cumulative_transform_[1][2] / res_y * | 363 | cumulative_transform_[0][2] / res_x + |
3571 | 364 | cumulative_transform_[1][2] / res_y); | 364 | cumulative_transform_[1][2] / res_y * |
3572 | 365 | } | 365 | cumulative_transform_[1][2] / res_y); |
3573 | 366 | 366 | } | |
3574 | 367 | float UGSlice_::CumulativePinch() const { | 367 | |
3575 | 368 | float pinch = original_radius_ ? radius_ / original_radius_ : 1; | 368 | float CumulativePinch() const { |
3576 | 369 | 369 | float pinch = original_radius_ > 0 ? radius_ / original_radius_ : 1; | |
3577 | 370 | return (pinch >= 1 ? pinch : 1 / pinch); | 370 | |
3578 | 371 | } | 371 | return( pinch < 1 ? 1 / pinch : pinch ); |
3579 | 372 | 372 | } | |
3580 | 373 | UGGestureTypeMask UGSlice_::CheckRecognition( | 373 | }; |
3581 | 374 | const UGSubscription_& subscription) { | 374 | |
3582 | 375 | if ((subscription.mask() & UGGestureTypeDrag) && | 375 | |
3583 | 376 | (!subscription.drag().timeout() || | 376 | |
3584 | 377 | CumulativeTime() < subscription.drag().timeout()) && | 377 | UGSlice::UGSlice( const SharedGesture & gesture, |
3585 | 378 | CumulativeDrag2() > subscription.drag().threshold()) | 378 | UFEvent event, |
3586 | 379 | recognized_ |= UGGestureTypeDrag; | 379 | const TouchSet & touches, |
3587 | 380 | 380 | UGGestureTypeMask recognized) | |
3588 | 381 | if ((subscription.mask() & UGGestureTypePinch) && | 381 | : d_( new Private( gesture, event, touches, recognized ) ) { |
3589 | 382 | (!subscription.pinch().timeout() || | 382 | |
3590 | 383 | CumulativeTime() < subscription.pinch().timeout()) && | 383 | } |
3591 | 384 | CumulativePinch() > subscription.pinch().threshold()) | 384 | |
3592 | 385 | recognized_ |= UGGestureTypePinch; | 385 | UGSlice::UGSlice( const SharedUGSlice & prev, |
3593 | 386 | 386 | UFEvent event, | |
3594 | 387 | if ((subscription.mask() & UGGestureTypeRotate) && | 387 | const TouchSet& touches ) |
3595 | 388 | (!subscription.rotate().timeout() || | 388 | : d_( new Private( prev, event, touches ) ) { |
3596 | 389 | CumulativeTime() < subscription.rotate().timeout()) && | 389 | } |
3597 | 390 | fabsf(angle_ - original_angle_) > subscription.rotate().threshold()) | 390 | |
3598 | 391 | recognized_ |= UGGestureTypeRotate; | 391 | UGSlice* UGSlice::NewUGSlice( const SharedGesture & gesture, |
3599 | 392 | 392 | UFEvent event, | |
3600 | 393 | if ((subscription.mask() & UGGestureTypeTap) && | 393 | const TouchSet & touches, |
3601 | 394 | CumulativeTime() < subscription.tap().timeout() && | 394 | UGGestureTypeMask recognized ) { |
3602 | 395 | state_ == UGGestureStateEnd) | 395 | |
3603 | 396 | recognized_ |= UGGestureTypeTap; | 396 | UGSlice* slice = new UGSlice(gesture, event, touches, recognized); |
3604 | 397 | 397 | ||
3605 | 398 | if (subscription.mask() & UGGestureTypeTouch) | 398 | UFStatus status = frame_event_get_property( event, |
3606 | 399 | recognized_ |= UGGestureTypeTouch; | 399 | UFEventPropertyFrame, |
3607 | 400 | 400 | &slice->d_->frame_); | |
3608 | 401 | return recognized_; | 401 | if (status != UFStatusSuccess) { |
3609 | 402 | } | 402 | fprintf(stderr, "Warning: failed to get frame from event\n"); |
3610 | 403 | 403 | delete slice; | |
3611 | 404 | UGStatus UGSlice_::GetTouchId(unsigned int index, void* touch_id) const { | 404 | return NULL; |
3612 | 405 | auto it = touches_.begin(); | 405 | } |
3613 | 406 | for (unsigned int i = 0; i < index; ++i, ++it) | 406 | |
3614 | 407 | if (it == touches_.end()) | 407 | slice->d_->GetValues( touches, |
3615 | 408 | return UGStatusErrorInvalidIndex; | 408 | &slice->d_->original_center_x_, |
3616 | 409 | 409 | &slice->d_->original_center_y_, | |
3617 | 410 | *reinterpret_cast<unsigned int*>(touch_id) = *it; | 410 | &slice->d_->original_radius_, |
3618 | 411 | return UGStatusSuccess; | 411 | &slice->d_->original_angle_, |
3619 | 412 | } | 412 | true); |
3620 | 413 | 413 | ||
3621 | 414 | UGStatus UGSlice_::GetProperty(UGSliceProperty property, void* value) const { | 414 | slice->d_->radius_ = slice->d_->original_radius_; |
3622 | 415 | switch (property) { | 415 | slice->d_->angle_ = slice->d_->original_angle_; |
3623 | 416 | case UGSlicePropertyId: | 416 | |
3624 | 417 | *reinterpret_cast<unsigned int*>(value) = gesture_.lock()->id(); | 417 | return slice; |
3625 | 418 | return UGStatusSuccess; | 418 | } |
3626 | 419 | 419 | ||
3627 | 420 | case UGSlicePropertyState: | 420 | UGSlice* UGSlice::NewUGSlice(const SharedUGSlice& prev, UFEvent event, |
3628 | 421 | *reinterpret_cast<UGGestureState*>(value) = state_; | 421 | const TouchSet& touches) { |
3629 | 422 | return UGStatusSuccess; | 422 | UGSlice* slice = new UGSlice(prev, event, touches); |
3630 | 423 | 423 | ||
3631 | 424 | case UGSlicePropertySubscription: | 424 | UFStatus status = frame_event_get_property( event, |
3632 | 425 | *reinterpret_cast<UGSubscription*>(value) = gesture_.lock()->subscription(); | 425 | UFEventPropertyFrame, |
3633 | 426 | return UGStatusSuccess; | 426 | &slice->d_->frame_ ); |
3634 | 427 | 427 | if (status != UFStatusSuccess) { | |
3635 | 428 | case UGSlicePropertyRecognized: | 428 | fprintf(stderr, "Warning: failed to get frame from event\n"); |
3636 | 429 | *reinterpret_cast<UGGestureTypeMask*>(value) = recognized_; | 429 | delete slice; |
3637 | 430 | return UGStatusSuccess; | 430 | return NULL; |
3638 | 431 | 431 | } | |
3639 | 432 | case UGSlicePropertyNumTouches: | 432 | |
3640 | 433 | *reinterpret_cast<unsigned int*>(value) = touches_.size(); | 433 | if (slice->d_->touch_count_changed_) { |
3641 | 434 | return UGStatusSuccess; | 434 | slice->d_->GetValues( touches, |
3642 | 435 | 435 | &slice->d_->original_center_x_, | |
3643 | 436 | case UGSlicePropertyFrame: | 436 | &slice->d_->original_center_y_, |
3644 | 437 | *reinterpret_cast<UFFrame*>(value) = frame_; | 437 | &slice->d_->original_radius_, |
3645 | 438 | return UGStatusSuccess; | 438 | &slice->d_->original_angle_, |
3646 | 439 | 439 | true); | |
3647 | 440 | case UGSlicePropertyOriginalCenterX: | 440 | slice->d_->radius_ = slice->d_->original_radius_; |
3648 | 441 | *reinterpret_cast<float*>(value) = original_center_x_; | 441 | slice->d_->angle_ = slice->d_->original_angle_; |
3649 | 442 | return UGStatusSuccess; | 442 | } else { |
3650 | 443 | 443 | slice->d_->SetTransforms(); | |
3651 | 444 | case UGSlicePropertyOriginalCenterY: | 444 | slice->d_->SetCenterOfRotation(); |
3652 | 445 | *reinterpret_cast<float*>(value) = original_center_y_; | 445 | slice->d_->CheckGestureEnd(); |
3653 | 446 | return UGStatusSuccess; | 446 | } |
3654 | 447 | 447 | ||
3655 | 448 | case UGSlicePropertyOriginalRadius: | 448 | return slice; |
3656 | 449 | *reinterpret_cast<float*>(value) = original_radius_; | 449 | } |
3657 | 450 | return UGStatusSuccess; | 450 | |
3658 | 451 | 451 | UGGestureTypeMask UGSlice::CheckRecognition( const UGSubscription & subscription ) { | |
3659 | 452 | case UGSlicePropertyTransform: | 452 | if ((subscription.mask() & UGGestureTypeDrag ) && |
3660 | 453 | *reinterpret_cast<UGTransform**>(value) = &transform_; | 453 | (!subscription.drag().timeout_ || |
3661 | 454 | return UGStatusSuccess; | 454 | d_->CumulativeTime() < subscription.drag().timeout_) && |
3662 | 455 | 455 | d_->CumulativeDrag2() > subscription.drag().threshold_) | |
3663 | 456 | case UGSlicePropertyCumulativeTransform: | 456 | d_->recognized_ |= UGGestureTypeDrag; |
3664 | 457 | *reinterpret_cast<UGTransform**>(value) = &cumulative_transform_; | 457 | |
3665 | 458 | return UGStatusSuccess; | 458 | if ((subscription.mask() & UGGestureTypePinch) && |
3666 | 459 | 459 | (!subscription.pinch().timeout_ || | |
3667 | 460 | case UGSlicePropertyCenterOfRotationX: | 460 | d_->CumulativeTime() < subscription.pinch().timeout_) && |
3668 | 461 | *reinterpret_cast<float*>(value) = center_of_rotation_x_; | 461 | d_->CumulativePinch() > subscription.pinch().threshold_) |
3669 | 462 | return UGStatusSuccess; | 462 | d_->recognized_ |= UGGestureTypePinch; |
3670 | 463 | 463 | ||
3671 | 464 | case UGSlicePropertyCenterOfRotationY: | 464 | if ((subscription.mask() & UGGestureTypeRotate) && |
3672 | 465 | *reinterpret_cast<float*>(value) = center_of_rotation_y_; | 465 | (!subscription.rotate().timeout_ || |
3673 | 466 | return UGStatusSuccess; | 466 | d_->CumulativeTime() < subscription.rotate().timeout_) && |
3674 | 467 | } | 467 | ::fabsf( d_->angle_ - d_->original_angle_) > subscription.rotate().threshold_) |
3675 | 468 | 468 | d_->recognized_ |= UGGestureTypeRotate; | |
3676 | 469 | return UGStatusErrorUnknownProperty; | 469 | |
3677 | 470 | } | 470 | if ((subscription.mask() & UGGestureTypeTap) && |
3678 | 471 | 471 | d_->CumulativeTime() < subscription.tap().timeout_ && | |
3679 | 472 | UGSlice_::~UGSlice_() { | 472 | d_->state_ == UGGestureStateEnd) |
3680 | 473 | frame_event_unref(event_); | 473 | d_->recognized_ |= UGGestureTypeTap; |
3681 | 474 | } | 474 | |
3682 | 475 | 475 | if (subscription.mask() & UGGestureTypeTouch) | |
3683 | 476 | extern "C" { | 476 | d_->recognized_ |= UGGestureTypeTouch; |
3684 | 477 | 477 | ||
3685 | 478 | UGStatus grail_slice_get_property(const UGSlice slice, UGSliceProperty property, | 478 | return( d_->recognized_ ); |
3686 | 479 | void* value) { | 479 | } |
3687 | 480 | return slice->GetProperty(property, value); | 480 | |
3688 | 481 | } | 481 | // Might be a performance penalty. |
3689 | 482 | 482 | UGStatus UGSlice::GetTouchId(unsigned int index, void* touch_id) const { | |
3690 | 483 | unsigned int grail_slice_get_id(const UGSlice slice) { | 483 | |
3691 | 484 | unsigned int id; | 484 | assert( touch_id == NULL ); |
3692 | 485 | UGStatus status = slice->GetProperty(UGSlicePropertyId, &id); | 485 | |
3693 | 486 | assert(status == UGStatusSuccess); | 486 | auto it = d_->touches_.begin(); |
3694 | 487 | return id; | 487 | for( unsigned int i = 0; i < index; ++i, ++it ) |
3695 | 488 | } | 488 | if( it == d_->touches_.end() ) |
3696 | 489 | 489 | return UGStatusErrorInvalidIndex; | |
3697 | 490 | UGGestureState grail_slice_get_state(const UGSlice slice) { | 490 | |
3698 | 491 | UGGestureState state; | 491 | *reinterpret_cast<unsigned int*>( touch_id ) = *it; |
3699 | 492 | UGStatus status = slice->GetProperty(UGSlicePropertyState, &state); | 492 | return( UGStatusSuccess ); |
3700 | 493 | assert(status == UGStatusSuccess); | 493 | } |
3701 | 494 | return state; | 494 | |
3702 | 495 | } | 495 | UGStatus UGSlice::GetProperty(UGSliceProperty property, void* value) const { |
3703 | 496 | 496 | assert( value == NULL ); | |
3704 | 497 | UGGestureTypeMask grail_slice_get_recognized(const UGSlice slice) { | 497 | switch( property ) { |
3705 | 498 | UGGestureTypeMask mask; | 498 | case UGSlicePropertyId: |
3706 | 499 | UGStatus status = slice->GetProperty(UGSlicePropertyRecognized, &mask); | 499 | *reinterpret_cast<unsigned int*>(value) = d_->gesture_.lock()->id(); |
3707 | 500 | assert(status == UGStatusSuccess); | 500 | return UGStatusSuccess; |
3708 | 501 | return mask; | 501 | |
3709 | 502 | } | 502 | case UGSlicePropertyState: |
3710 | 503 | 503 | *reinterpret_cast<UGGestureState*>( value ) = d_->state_; | |
3711 | 504 | UGSubscription grail_slice_get_subscription(const UGSlice slice) { | 504 | return UGStatusSuccess; |
3712 | 505 | UGSubscription subscription; | 505 | |
3713 | 506 | UGStatus status = slice->GetProperty(UGSlicePropertySubscription, | 506 | case UGSlicePropertySubscription: |
3714 | 507 | &subscription); | 507 | *reinterpret_cast<void**>( value ) = d_->gesture_.lock()->subscription(); |
3715 | 508 | assert(status == UGStatusSuccess); | 508 | return UGStatusSuccess; |
3716 | 509 | return subscription; | 509 | |
3717 | 510 | } | 510 | case UGSlicePropertyRecognized: |
3718 | 511 | 511 | *reinterpret_cast<UGGestureTypeMask*>(value) = d_->recognized_; | |
3719 | 512 | unsigned int grail_slice_get_num_touches(const UGSlice slice) { | 512 | return UGStatusSuccess; |
3720 | 513 | unsigned int num_touches; | 513 | |
3721 | 514 | UGStatus status = slice->GetProperty(UGSlicePropertyNumTouches, &num_touches); | 514 | case UGSlicePropertyNumTouches: |
3722 | 515 | assert(status == UGStatusSuccess); | 515 | *reinterpret_cast<unsigned int*>(value) = d_->touches_.size(); |
3723 | 516 | return num_touches; | 516 | return UGStatusSuccess; |
3724 | 517 | } | 517 | |
3725 | 518 | 518 | case UGSlicePropertyFrame: | |
3726 | 519 | UGStatus grail_slice_get_touch_id(const UGSlice slice, unsigned int index, | 519 | *reinterpret_cast<UFFrame*>(value) = d_->frame_; |
3727 | 520 | void *touch_id) { | 520 | return UGStatusSuccess; |
3728 | 521 | return slice->GetTouchId(index, touch_id); | 521 | |
3729 | 522 | } | 522 | case UGSlicePropertyOriginalCenterX: |
3730 | 523 | 523 | *reinterpret_cast<float*>(value) = d_->original_center_x_; | |
3731 | 524 | float grail_slice_get_original_center_x(const UGSlice slice) { | 524 | return UGStatusSuccess; |
3732 | 525 | float x; | 525 | |
3733 | 526 | UGStatus status = slice->GetProperty(UGSlicePropertyOriginalCenterX, &x); | 526 | case UGSlicePropertyOriginalCenterY: |
3734 | 527 | assert(status == UGStatusSuccess); | 527 | *reinterpret_cast<float*>(value) = d_->original_center_y_; |
3735 | 528 | return x; | 528 | return UGStatusSuccess; |
3736 | 529 | } | 529 | |
3737 | 530 | 530 | case UGSlicePropertyOriginalRadius: | |
3738 | 531 | float grail_slice_get_original_center_y(const UGSlice slice) { | 531 | *reinterpret_cast<float*>(value) = d_->original_radius_; |
3739 | 532 | float y; | 532 | return UGStatusSuccess; |
3740 | 533 | UGStatus status = slice->GetProperty(UGSlicePropertyOriginalCenterY, &y); | 533 | |
3741 | 534 | assert(status == UGStatusSuccess); | 534 | case UGSlicePropertyTransform: |
3742 | 535 | return y; | 535 | *reinterpret_cast<UGTransform**>(value) = &d_->transform_; |
3743 | 536 | } | 536 | return UGStatusSuccess; |
3744 | 537 | 537 | ||
3745 | 538 | float grail_slice_get_original_radius(const UGSlice slice) { | 538 | case UGSlicePropertyCumulativeTransform: |
3746 | 539 | float radius; | 539 | *reinterpret_cast<UGTransform**>(value) = &d_->cumulative_transform_; |
3747 | 540 | UGStatus status = slice->GetProperty(UGSlicePropertyOriginalRadius, &radius); | 540 | return UGStatusSuccess; |
3748 | 541 | assert(status == UGStatusSuccess); | 541 | |
3749 | 542 | return radius; | 542 | case UGSlicePropertyCenterOfRotationX: |
3750 | 543 | } | 543 | *reinterpret_cast<float*>(value) = d_->center_of_rotation_x_; |
3751 | 544 | 544 | return UGStatusSuccess; | |
3752 | 545 | float grail_slice_get_center_of_rotation_x(const UGSlice slice) { | 545 | |
3753 | 546 | float x; | 546 | case UGSlicePropertyCenterOfRotationY: |
3754 | 547 | UGStatus status = slice->GetProperty(UGSlicePropertyCenterOfRotationX, &x); | 547 | *reinterpret_cast<float*>(value) = d_->center_of_rotation_y_; |
3755 | 548 | assert(status == UGStatusSuccess); | 548 | return UGStatusSuccess; |
3756 | 549 | return x; | 549 | default: |
3757 | 550 | } | 550 | break; |
3758 | 551 | 551 | } | |
3759 | 552 | float grail_slice_get_center_of_rotation_y(const UGSlice slice) { | 552 | |
3760 | 553 | float y; | 553 | return UGStatusErrorUnknownProperty; |
3761 | 554 | UGStatus status = slice->GetProperty(UGSlicePropertyCenterOfRotationY, &y); | 554 | } |
3762 | 555 | assert(status == UGStatusSuccess); | 555 | |
3763 | 556 | return y; | 556 | void UGSlice::ReferenceGesture() { |
3764 | 557 | } | 557 | d_->gesture_ref_ = d_->gesture_.lock(); |
3765 | 558 | 558 | } | |
3766 | 559 | const UGTransform *grail_slice_get_transform(const UGSlice slice) { | 559 | |
3767 | 560 | UGTransform *transform; | 560 | uint64_t UGSlice::time() const { |
3768 | 561 | UGStatus status = slice->GetProperty(UGSlicePropertyTransform, &transform); | 561 | return d_->time_; |
3769 | 562 | assert(status == UGStatusSuccess); | 562 | } |
3770 | 563 | return transform; | 563 | |
3771 | 564 | } | 564 | const TouchSet & UGSlice::touches() { |
3772 | 565 | 565 | return d_->touches_; | |
3773 | 566 | const UGTransform *grail_slice_get_cumulative_transform(const UGSlice slice) { | 566 | } |
3774 | 567 | UGTransform *transform; | 567 | |
3775 | 568 | UGStatus status = slice->GetProperty(UGSlicePropertyCumulativeTransform, | 568 | const UFFrame & UGSlice::frame() { |
3776 | 569 | &transform); | 569 | return d_->frame_; |
3777 | 570 | assert(status == UGStatusSuccess); | 570 | } |
3778 | 571 | return transform; | 571 | |
3779 | 572 | } | 572 | UGGestureState UGSlice::state() const { |
3780 | 573 | 573 | return d_->state_; | |
3781 | 574 | const UFFrame grail_slice_get_frame(const UGSlice slice) { | 574 | } |
3782 | 575 | UFFrame frame; | 575 | |
3783 | 576 | UGStatus status = slice->GetProperty(UGSlicePropertyFrame, &frame); | 576 | void UGSlice::set_state( UGGestureState state ) { |
3784 | 577 | assert(status == UGStatusSuccess); | 577 | d_->state_ = state; |
3785 | 578 | return frame; | 578 | } |
3786 | 579 | } | 579 | |
3787 | 580 | 580 | } | |
3788 | 581 | } // extern "C" | 581 | // extern "C" { |
3789 | 582 | |||
3790 | 583 | UGStatus grail_slice_get_property( const UGSlice slice, | ||
3791 | 584 | UGSliceProperty property, | ||
3792 | 585 | void* value) { | ||
3793 | 586 | if( slice == NULL ) | ||
3794 | 587 | return( UGStatusErrorGeneric ); | ||
3795 | 588 | |||
3796 | 589 | return static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(property, value); | ||
3797 | 590 | } | ||
3798 | 591 | |||
3799 | 592 | unsigned int grail_slice_get_id(const UGSlice slice) { | ||
3800 | 593 | if( slice == NULL ) | ||
3801 | 594 | return( UGStatusErrorGeneric ); | ||
3802 | 595 | unsigned int id; | ||
3803 | 596 | UGStatus status = static_cast< const utouch::grail::UGSlice*>( slice )->GetProperty(UGSlicePropertyId, &id); | ||
3804 | 597 | assert(status == UGStatusSuccess); | ||
3805 | 598 | return id; | ||
3806 | 599 | } | ||
3807 | 600 | |||
3808 | 601 | UGGestureState grail_slice_get_state(const UGSlice slice) { | ||
3809 | 602 | assert( slice == NULL ); | ||
3810 | 603 | UGGestureState state; | ||
3811 | 604 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyState, &state); | ||
3812 | 605 | assert(status == UGStatusSuccess); | ||
3813 | 606 | return state; | ||
3814 | 607 | } | ||
3815 | 608 | |||
3816 | 609 | UGGestureTypeMask grail_slice_get_recognized(const UGSlice slice) { | ||
3817 | 610 | if( slice == NULL ) | ||
3818 | 611 | return( UGStatusErrorGeneric ); | ||
3819 | 612 | |||
3820 | 613 | UGGestureTypeMask mask; | ||
3821 | 614 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyRecognized, &mask); | ||
3822 | 615 | assert(status == UGStatusSuccess); | ||
3823 | 616 | return mask; | ||
3824 | 617 | } | ||
3825 | 618 | |||
3826 | 619 | UGSubscription grail_slice_get_subscription(const UGSlice slice) { | ||
3827 | 620 | assert( slice == NULL ); | ||
3828 | 621 | |||
3829 | 622 | UGSubscription subscription; | ||
3830 | 623 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertySubscription, | ||
3831 | 624 | &subscription); | ||
3832 | 625 | assert(status == UGStatusSuccess); | ||
3833 | 626 | return subscription; | ||
3834 | 627 | } | ||
3835 | 628 | |||
3836 | 629 | unsigned int grail_slice_get_num_touches(const UGSlice slice) { | ||
3837 | 630 | assert( slice == NULL ); | ||
3838 | 631 | |||
3839 | 632 | unsigned int num_touches; | ||
3840 | 633 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyNumTouches, &num_touches); | ||
3841 | 634 | assert(status == UGStatusSuccess); | ||
3842 | 635 | return num_touches; | ||
3843 | 636 | } | ||
3844 | 637 | |||
3845 | 638 | UGStatus grail_slice_get_touch_id(const UGSlice slice, unsigned int index, | ||
3846 | 639 | void *touch_id) { | ||
3847 | 640 | if( slice == NULL ) | ||
3848 | 641 | return( UGStatusErrorGeneric ); | ||
3849 | 642 | return static_cast< const utouch::grail::UGSlice* >( slice )->GetTouchId(index, touch_id); | ||
3850 | 643 | } | ||
3851 | 644 | |||
3852 | 645 | float grail_slice_get_original_center_x(const UGSlice slice) { | ||
3853 | 646 | if( slice == NULL ) | ||
3854 | 647 | return( UGStatusErrorGeneric ); | ||
3855 | 648 | float x; | ||
3856 | 649 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalCenterX, &x); | ||
3857 | 650 | assert(status == UGStatusSuccess); | ||
3858 | 651 | return x; | ||
3859 | 652 | } | ||
3860 | 653 | |||
3861 | 654 | float grail_slice_get_original_center_y(const UGSlice slice) { | ||
3862 | 655 | if( slice == NULL ) | ||
3863 | 656 | return( UGStatusErrorGeneric ); | ||
3864 | 657 | float y; | ||
3865 | 658 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalCenterY, &y); | ||
3866 | 659 | assert(status == UGStatusSuccess); | ||
3867 | 660 | return y; | ||
3868 | 661 | } | ||
3869 | 662 | |||
3870 | 663 | float grail_slice_get_original_radius(const UGSlice slice) { | ||
3871 | 664 | if( slice == NULL ) | ||
3872 | 665 | return( UGStatusErrorGeneric ); | ||
3873 | 666 | float radius; | ||
3874 | 667 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalRadius, &radius); | ||
3875 | 668 | assert(status == UGStatusSuccess); | ||
3876 | 669 | return radius; | ||
3877 | 670 | } | ||
3878 | 671 | |||
3879 | 672 | float grail_slice_get_center_of_rotation_x(const UGSlice slice) { | ||
3880 | 673 | if( slice == NULL ) | ||
3881 | 674 | return( UGStatusErrorGeneric ); | ||
3882 | 675 | float x; | ||
3883 | 676 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCenterOfRotationX, &x); | ||
3884 | 677 | assert(status == UGStatusSuccess); | ||
3885 | 678 | return x; | ||
3886 | 679 | } | ||
3887 | 680 | |||
3888 | 681 | float grail_slice_get_center_of_rotation_y(const UGSlice slice) { | ||
3889 | 682 | if( slice == NULL ) | ||
3890 | 683 | return( UGStatusErrorGeneric ); | ||
3891 | 684 | float y; | ||
3892 | 685 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCenterOfRotationY, &y); | ||
3893 | 686 | assert(status == UGStatusSuccess); | ||
3894 | 687 | return y; | ||
3895 | 688 | } | ||
3896 | 689 | |||
3897 | 690 | const UGTransform *grail_slice_get_transform(const UGSlice slice) { | ||
3898 | 691 | assert( slice == NULL ); | ||
3899 | 692 | |||
3900 | 693 | UGTransform *transform; | ||
3901 | 694 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyTransform, &transform); | ||
3902 | 695 | assert(status == UGStatusSuccess); | ||
3903 | 696 | return transform; | ||
3904 | 697 | } | ||
3905 | 698 | |||
3906 | 699 | const UGTransform *grail_slice_get_cumulative_transform(const UGSlice slice) { | ||
3907 | 700 | assert( slice == NULL ); | ||
3908 | 701 | |||
3909 | 702 | UGTransform *transform; | ||
3910 | 703 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCumulativeTransform, | ||
3911 | 704 | &transform); | ||
3912 | 705 | assert(status == UGStatusSuccess); | ||
3913 | 706 | return transform; | ||
3914 | 707 | } | ||
3915 | 708 | |||
3916 | 709 | const UFFrame grail_slice_get_frame(const UGSlice slice) { | ||
3917 | 710 | assert( slice == NULL ); | ||
3918 | 711 | |||
3919 | 712 | UFFrame frame; | ||
3920 | 713 | UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyFrame, &frame); | ||
3921 | 714 | assert(status == UGStatusSuccess); | ||
3922 | 715 | return frame; | ||
3923 | 716 | } | ||
3924 | 717 | } | ||
3925 | 718 | // } // extern "C" | ||
3926 | 582 | 719 | ||
3927 | === modified file 'src/v3/slice.h' | |||
3928 | --- src/v3/slice.h 2011-10-20 23:55:57 +0000 | |||
3929 | +++ src/v3/slice.h 2011-11-01 21:20:40 +0000 | |||
3930 | @@ -27,69 +27,61 @@ | |||
3931 | 27 | 27 | ||
3932 | 28 | #include "utouch/grail.h" | 28 | #include "utouch/grail.h" |
3933 | 29 | 29 | ||
3999 | 30 | class Gesture; | 30 | namespace utouch { |
4000 | 31 | 31 | namespace grail { | |
4001 | 32 | typedef std::shared_ptr<Gesture> SharedGesture; | 32 | |
4002 | 33 | typedef std::shared_ptr<UGSlice_> SharedUGSlice_; | 33 | class Gesture; |
4003 | 34 | typedef std::set<unsigned int> TouchSet; | 34 | |
4004 | 35 | 35 | class UGSlice; | |
4005 | 36 | class UGSlice_ { | 36 | class UGSubscription; |
4006 | 37 | public: | 37 | |
4007 | 38 | static UGSlice_* NewUGSlice_(const SharedGesture& gesture, UFEvent event, | 38 | typedef std::shared_ptr<Gesture> SharedGesture; |
4008 | 39 | const TouchSet& touches, | 39 | typedef std::shared_ptr<UGSlice> SharedUGSlice; |
4009 | 40 | UGGestureTypeMask recognized); | 40 | typedef std::set<unsigned int> TouchSet; |
4010 | 41 | static UGSlice_* NewUGSlice_(const SharedUGSlice_& prev, UFEvent event, | 41 | |
4011 | 42 | const TouchSet& touches); | 42 | class UGSlice { |
4012 | 43 | 43 | public: | |
4013 | 44 | ~UGSlice_(); | 44 | |
4014 | 45 | 45 | static UGSlice* NewUGSlice(const SharedGesture& gesture, UFEvent event, | |
4015 | 46 | void CheckGestureEnd(); | 46 | const TouchSet& touches, |
4016 | 47 | UGGestureTypeMask CheckRecognition(const UGSubscription_& subscription); | 47 | UGGestureTypeMask recognized); |
4017 | 48 | UGStatus GetTouchId(unsigned int index, void* touch_id) const; | 48 | static UGSlice* NewUGSlice(const SharedUGSlice& prev, UFEvent event, |
4018 | 49 | UGStatus GetProperty(UGSliceProperty property, void* value) const; | 49 | const TouchSet& touches); |
4019 | 50 | void ReferenceGesture() { gesture_ref_ = gesture_.lock(); } | 50 | |
4020 | 51 | 51 | void CheckGestureEnd(); | |
4021 | 52 | uint64_t time() const { return time_; } | 52 | |
4022 | 53 | const TouchSet& touches() { return touches_; } | 53 | UGGestureTypeMask CheckRecognition( const UGSubscription & subscription ); |
4023 | 54 | const UFFrame& frame() { return frame_; } | 54 | |
4024 | 55 | UGGestureState state() const { return state_; } | 55 | UGStatus GetTouchId(unsigned int index, void* touch_id) const; |
4025 | 56 | void set_state(UGGestureState state) { state_ = state; } | 56 | |
4026 | 57 | 57 | UGStatus GetProperty(UGSliceProperty property, void* value) const; | |
4027 | 58 | UGSlice_(const UGSlice_&) = delete; | 58 | |
4028 | 59 | void operator=(const UGSlice_&) = delete; | 59 | void ReferenceGesture(); |
4029 | 60 | 60 | ||
4030 | 61 | private: | 61 | uint64_t time() const; |
4031 | 62 | const std::weak_ptr<Gesture> gesture_; | 62 | const TouchSet& touches(); |
4032 | 63 | SharedGesture gesture_ref_; | 63 | const UFFrame& frame(); |
4033 | 64 | const UFEvent event_; | 64 | UGGestureState state() const; |
4034 | 65 | UFFrame frame_; | 65 | void set_state( UGGestureState state ); |
4035 | 66 | TouchSet touches_; | 66 | |
4036 | 67 | uint64_t time_; | 67 | // Disable compiler generated c'tor, copy c'tor and assignment operator. |
4037 | 68 | UGGestureState state_; | 68 | UGSlice( const UGSlice & ) = delete; |
4038 | 69 | float original_center_x_; | 69 | // void operator=( const UGSlice & ) = delete; |
4039 | 70 | float original_center_y_; | 70 | bool operator==( const UGSlice & ) const = delete; |
4040 | 71 | float original_radius_; | 71 | |
4041 | 72 | float original_angle_; | 72 | protected: |
4042 | 73 | float radius_; | 73 | struct Private; |
4043 | 74 | float angle_; | 74 | std::shared_ptr< Private > d_; |
4044 | 75 | float transform_[3][3]; | 75 | |
4045 | 76 | float cumulative_transform_[3][3]; | 76 | UGSlice( const SharedGesture & gesture, |
4046 | 77 | float center_of_rotation_x_; | 77 | UFEvent event, |
4047 | 78 | float center_of_rotation_y_; | 78 | const TouchSet & touches, |
4048 | 79 | UGGestureTypeMask recognized_; | 79 | UGGestureTypeMask recognized); |
4049 | 80 | bool touch_count_changed_; | 80 | |
4050 | 81 | 81 | UGSlice( const SharedUGSlice & prev, | |
4051 | 82 | UGSlice_(const SharedGesture& gesture, UFEvent event, const TouchSet& touches, | 82 | UFEvent event, |
4052 | 83 | UGGestureTypeMask recognized); | 83 | const TouchSet& touches ); |
4053 | 84 | UGSlice_(const SharedUGSlice_& prev, UFEvent event, const TouchSet& touches); | 84 | }; |
4054 | 85 | 85 | } | |
4055 | 86 | void GetValues(const TouchSet& touches, float* x, float* y, float* radius, | 86 | } |
3991 | 87 | float* angle, bool init); | ||
3992 | 88 | void SetTransforms(); | ||
3993 | 89 | void SetCenterOfRotation(); | ||
3994 | 90 | uint64_t CumulativeTime() const; | ||
3995 | 91 | float CumulativeDrag2() const; | ||
3996 | 92 | float CumulativePinch() const; | ||
3997 | 93 | }; | ||
3998 | 94 | |||
4056 | 95 | #endif // UTOUCH_GRAIL_SLICE_H_ | 87 | #endif // UTOUCH_GRAIL_SLICE_H_ |
4057 | 96 | 88 | ||
4058 | === modified file 'src/v3/subscription.cpp' | |||
4059 | --- src/v3/subscription.cpp 2011-10-20 16:00:48 +0000 | |||
4060 | +++ src/v3/subscription.cpp 2011-11-01 21:20:40 +0000 | |||
4061 | @@ -21,265 +21,303 @@ | |||
4062 | 21 | 21 | ||
4063 | 22 | #include "v3/subscription.h" | 22 | #include "v3/subscription.h" |
4064 | 23 | 23 | ||
4308 | 24 | #include <math.h> | 24 | #include <cassert> |
4309 | 25 | 25 | #include <cmath> | |
4310 | 26 | Limit::Limit(UGGestureType type) { | 26 | |
4311 | 27 | switch (type) { | 27 | namespace utouch { |
4312 | 28 | case UGGestureTypeDrag: | 28 | namespace grail { |
4313 | 29 | timeout_ = 300; | 29 | |
4314 | 30 | threshold_ = 2.6; | 30 | UGSubscription::Limit::Limit(UGGestureType type) { |
4315 | 31 | break; | 31 | switch (type) { |
4316 | 32 | 32 | case UGGestureTypeDrag: | |
4317 | 33 | case UGGestureTypePinch: | 33 | timeout_ = 300; |
4318 | 34 | timeout_ = 300; | 34 | threshold_ = 2.6; |
4319 | 35 | threshold_ = 1.1; /* Different from grail v1, ratio instead of delta */ | 35 | break; |
4320 | 36 | break; | 36 | |
4321 | 37 | 37 | case UGGestureTypePinch: | |
4322 | 38 | case UGGestureTypeRotate: | 38 | timeout_ = 300; |
4323 | 39 | timeout_ = 500; | 39 | threshold_ = 1.1; /* Different from grail v1, ratio instead of delta */ |
4324 | 40 | threshold_ = 2 * M_PI / 50; | 40 | break; |
4325 | 41 | break; | 41 | |
4326 | 42 | 42 | case UGGestureTypeRotate: | |
4327 | 43 | case UGGestureTypeTap: | 43 | timeout_ = 500; |
4328 | 44 | timeout_ = 300; | 44 | threshold_ = 2 * M_PI / 50; |
4329 | 45 | threshold_ = 0; | 45 | break; |
4330 | 46 | break; | 46 | |
4331 | 47 | 47 | case UGGestureTypeTap: | |
4332 | 48 | case UGGestureTypeTouch: | 48 | timeout_ = 300; |
4333 | 49 | timeout_ = 0; | 49 | threshold_ = 0; |
4334 | 50 | threshold_ = 0; | 50 | break; |
4335 | 51 | break; | 51 | |
4336 | 52 | } | 52 | case UGGestureTypeTouch: |
4337 | 53 | } | 53 | timeout_ = 0; |
4338 | 54 | 54 | threshold_ = 0; | |
4339 | 55 | UGSubscription_::UGSubscription_() | 55 | break; |
4340 | 56 | : device_(0), | 56 | } |
4341 | 57 | window_(0), | 57 | } |
4342 | 58 | mask_(0), | 58 | |
4343 | 59 | touches_start_(2), | 59 | struct UGSubscription::Private { |
4344 | 60 | touches_min_(0), | 60 | |
4345 | 61 | touches_max_(0), | 61 | Private() : device_(0), |
4346 | 62 | drag_(UGGestureTypeDrag), | 62 | window_(0), |
4347 | 63 | pinch_(UGGestureTypePinch), | 63 | mask_(0), |
4348 | 64 | rotate_(UGGestureTypeRotate), | 64 | touches_start_(2), |
4349 | 65 | tap_(UGGestureTypeTap) { | 65 | touches_min_(0), |
4350 | 66 | } | 66 | touches_max_(0), |
4351 | 67 | 67 | drag_(UGGestureTypeDrag), | |
4352 | 68 | bool UGSubscription_::IsValid() const { | 68 | pinch_(UGGestureTypePinch), |
4353 | 69 | if (!device_ || | 69 | rotate_(UGGestureTypeRotate), |
4354 | 70 | !window_ || | 70 | tap_(UGGestureTypeTap) { |
4355 | 71 | mask_ == 0 || | 71 | } |
4356 | 72 | (touches_max_ && touches_start_ > touches_max_) || | 72 | |
4357 | 73 | (touches_min_ && touches_start_ < touches_min_)) | 73 | UFDevice device_; |
4358 | 74 | return false; | 74 | Window window_; |
4359 | 75 | 75 | UGGestureTypeMask mask_; | |
4360 | 76 | return true; | 76 | unsigned int touches_start_; |
4361 | 77 | } | 77 | unsigned int touches_min_; |
4362 | 78 | 78 | unsigned int touches_max_; | |
4363 | 79 | UGStatus UGSubscription_::SetProperty(UGSubscriptionProperty property, | 79 | Limit drag_; |
4364 | 80 | const void* value) { | 80 | Limit pinch_; |
4365 | 81 | switch (property) { | 81 | Limit rotate_; |
4366 | 82 | case UGSubscriptionPropertyDevice: { | 82 | Limit tap_; |
4367 | 83 | UFDevice device = *reinterpret_cast<const UFDevice*>(value); | 83 | }; |
4368 | 84 | if (!device) | 84 | |
4369 | 85 | return UGStatusErrorInvalidValue; | 85 | UGSubscription::UGSubscription() |
4370 | 86 | device_ = device; | 86 | : d_( new Private() ) { |
4371 | 87 | return UGStatusSuccess; | 87 | } |
4372 | 88 | } | 88 | |
4373 | 89 | 89 | bool UGSubscription::IsValid() const { | |
4374 | 90 | case UGSubscriptionPropertyWindow: { | 90 | if (!d_->device_ || |
4375 | 91 | Window window = *reinterpret_cast<const Window*>(value); | 91 | !d_->window_ || |
4376 | 92 | if (!window) | 92 | d_->mask_ == 0 || |
4377 | 93 | return UGStatusErrorInvalidValue; | 93 | (d_->touches_max_ && d_->touches_start_ > d_->touches_max_) || |
4378 | 94 | window_ = window; | 94 | (d_->touches_min_ && d_->touches_start_ < d_->touches_min_)) |
4379 | 95 | return UGStatusSuccess; | 95 | return false; |
4380 | 96 | } | 96 | |
4381 | 97 | 97 | return true; | |
4382 | 98 | case UGSubscriptionPropertyMask: { | 98 | } |
4383 | 99 | UGGestureTypeMask mask = | 99 | |
4384 | 100 | *reinterpret_cast<const UGGestureTypeMask*>(value); | 100 | UGStatus UGSubscription::SetProperty(UGSubscriptionProperty property, |
4385 | 101 | if (mask == 0) | 101 | const void* value) { |
4386 | 102 | return UGStatusErrorInvalidValue; | 102 | |
4387 | 103 | mask_ = mask; | 103 | assert( value == NULL ); |
4388 | 104 | return UGStatusSuccess; | 104 | |
4389 | 105 | } | 105 | switch (property) { |
4390 | 106 | 106 | case UGSubscriptionPropertyDevice: { | |
4391 | 107 | case UGSubscriptionPropertyTouchesStart: { | 107 | UFDevice device = *reinterpret_cast<const UFDevice*>(value); |
4392 | 108 | unsigned int touches = *reinterpret_cast<const unsigned int*>(value); | 108 | if (!device) |
4393 | 109 | if (touches == 0 || touches > 5) | 109 | return UGStatusErrorInvalidValue; |
4394 | 110 | return UGStatusErrorInvalidValue; | 110 | d_->device_ = device; |
4395 | 111 | touches_start_ = touches; | 111 | return UGStatusSuccess; |
4396 | 112 | return UGStatusSuccess; | 112 | } |
4397 | 113 | } | 113 | |
4398 | 114 | 114 | case UGSubscriptionPropertyWindow: { | |
4399 | 115 | case UGSubscriptionPropertyTouchesMinimum: { | 115 | Window window = *reinterpret_cast<const Window*>(value); |
4400 | 116 | unsigned int touches = *reinterpret_cast<const unsigned int*>(value); | 116 | if (!window) |
4401 | 117 | if (touches == 0 || touches > 5) | 117 | return UGStatusErrorInvalidValue; |
4402 | 118 | return UGStatusErrorInvalidValue; | 118 | d_->window_ = window; |
4403 | 119 | touches_min_ = touches; | 119 | return UGStatusSuccess; |
4404 | 120 | return UGStatusSuccess; | 120 | } |
4405 | 121 | } | 121 | |
4406 | 122 | 122 | case UGSubscriptionPropertyMask: { | |
4407 | 123 | case UGSubscriptionPropertyTouchesMaximum: { | 123 | UGGestureTypeMask mask = |
4408 | 124 | unsigned int touches = *reinterpret_cast<const unsigned int*>(value); | 124 | *reinterpret_cast<const UGGestureTypeMask*>(value); |
4409 | 125 | if (touches == 0 || touches > 5) | 125 | if (mask == 0) |
4410 | 126 | return UGStatusErrorInvalidValue; | 126 | return UGStatusErrorInvalidValue; |
4411 | 127 | touches_max_ = touches; | 127 | d_->mask_ = mask; |
4412 | 128 | return UGStatusSuccess; | 128 | return UGStatusSuccess; |
4413 | 129 | } | 129 | } |
4414 | 130 | 130 | ||
4415 | 131 | case UGSubscriptionPropertyDragTimeout: { | 131 | case UGSubscriptionPropertyTouchesStart: { |
4416 | 132 | uint64_t timeout = *reinterpret_cast<const uint64_t*>(value); | 132 | unsigned int touches = *reinterpret_cast<const unsigned int*>(value); |
4417 | 133 | if (timeout < 0) | 133 | if (touches == 0 || touches > 5) |
4418 | 134 | return UGStatusErrorInvalidValue; | 134 | return UGStatusErrorInvalidValue; |
4419 | 135 | drag_.set_timeout(timeout); | 135 | d_->touches_start_ = touches; |
4420 | 136 | return UGStatusSuccess; | 136 | return UGStatusSuccess; |
4421 | 137 | } | 137 | } |
4422 | 138 | 138 | ||
4423 | 139 | case UGSubscriptionPropertyDragThreshold: { | 139 | case UGSubscriptionPropertyTouchesMinimum: { |
4424 | 140 | float threshold = *reinterpret_cast<const float*>(value); | 140 | unsigned int touches = *reinterpret_cast<const unsigned int*>(value); |
4425 | 141 | if (threshold < 0) | 141 | if (touches == 0 || touches > 5) |
4426 | 142 | return UGStatusErrorInvalidValue; | 142 | return UGStatusErrorInvalidValue; |
4427 | 143 | drag_.set_threshold(threshold); | 143 | d_->touches_min_ = touches; |
4428 | 144 | return UGStatusSuccess; | 144 | return UGStatusSuccess; |
4429 | 145 | } | 145 | } |
4430 | 146 | 146 | ||
4431 | 147 | case UGSubscriptionPropertyPinchTimeout: { | 147 | case UGSubscriptionPropertyTouchesMaximum: { |
4432 | 148 | uint64_t timeout = *reinterpret_cast<const uint64_t*>(value); | 148 | unsigned int touches = *reinterpret_cast<const unsigned int*>(value); |
4433 | 149 | if (timeout < 0) | 149 | if (touches == 0 || touches > 5) |
4434 | 150 | return UGStatusErrorInvalidValue; | 150 | return UGStatusErrorInvalidValue; |
4435 | 151 | pinch_.set_timeout(timeout); | 151 | d_->touches_max_ = touches; |
4436 | 152 | return UGStatusSuccess; | 152 | return UGStatusSuccess; |
4437 | 153 | } | 153 | } |
4438 | 154 | 154 | ||
4439 | 155 | case UGSubscriptionPropertyPinchThreshold: { | 155 | case UGSubscriptionPropertyDragTimeout: { |
4440 | 156 | float threshold = *reinterpret_cast<const float*>(value); | 156 | uint64_t timeout = *reinterpret_cast<const uint64_t*>(value); |
4441 | 157 | if (threshold < 0) | 157 | if (timeout < 0) |
4442 | 158 | return UGStatusErrorInvalidValue; | 158 | return UGStatusErrorInvalidValue; |
4443 | 159 | pinch_.set_threshold(threshold); | 159 | d_->drag_.timeout_ = timeout; |
4444 | 160 | return UGStatusSuccess; | 160 | return UGStatusSuccess; |
4445 | 161 | } | 161 | } |
4446 | 162 | 162 | ||
4447 | 163 | case UGSubscriptionPropertyRotateTimeout: { | 163 | case UGSubscriptionPropertyDragThreshold: { |
4448 | 164 | uint64_t timeout = *reinterpret_cast<const uint64_t*>(value); | 164 | float threshold = *reinterpret_cast<const float*>(value); |
4449 | 165 | if (timeout < 0) | 165 | if (threshold < 0) |
4450 | 166 | return UGStatusErrorInvalidValue; | 166 | return UGStatusErrorInvalidValue; |
4451 | 167 | rotate_.set_timeout(timeout); | 167 | d_->drag_.threshold_ = threshold; |
4452 | 168 | return UGStatusSuccess; | 168 | return UGStatusSuccess; |
4453 | 169 | } | 169 | } |
4454 | 170 | 170 | ||
4455 | 171 | case UGSubscriptionPropertyRotateThreshold: { | 171 | case UGSubscriptionPropertyPinchTimeout: { |
4456 | 172 | float threshold = *reinterpret_cast<const float*>(value); | 172 | uint64_t timeout = *reinterpret_cast<const uint64_t*>(value); |
4457 | 173 | if (threshold < 0) | 173 | if (timeout < 0) |
4458 | 174 | return UGStatusErrorInvalidValue; | 174 | return UGStatusErrorInvalidValue; |
4459 | 175 | rotate_.set_threshold(threshold); | 175 | d_->pinch_.timeout_ = timeout; |
4460 | 176 | return UGStatusSuccess; | 176 | return UGStatusSuccess; |
4461 | 177 | } | 177 | } |
4462 | 178 | 178 | ||
4463 | 179 | case UGSubscriptionPropertyTapTimeout: { | 179 | case UGSubscriptionPropertyPinchThreshold: { |
4464 | 180 | uint64_t timeout = *reinterpret_cast<const uint64_t*>(value); | 180 | float threshold = *reinterpret_cast<const float*>(value); |
4465 | 181 | if (timeout < 0) | 181 | if (threshold < 0) |
4466 | 182 | return UGStatusErrorInvalidValue; | 182 | return UGStatusErrorInvalidValue; |
4467 | 183 | tap_.set_timeout(timeout); | 183 | d_->pinch_.threshold_ = threshold; |
4468 | 184 | return UGStatusSuccess; | 184 | return UGStatusSuccess; |
4469 | 185 | } | 185 | } |
4470 | 186 | 186 | ||
4471 | 187 | case UGSubscriptionPropertyTapThreshold: { | 187 | case UGSubscriptionPropertyRotateTimeout: { |
4472 | 188 | float threshold = *reinterpret_cast<const float*>(value); | 188 | uint64_t timeout = *reinterpret_cast<const uint64_t*>(value); |
4473 | 189 | if (threshold < 0) | 189 | if (timeout < 0) |
4474 | 190 | return UGStatusErrorInvalidValue; | 190 | return UGStatusErrorInvalidValue; |
4475 | 191 | tap_.set_threshold(threshold); | 191 | d_->rotate_.timeout_ = timeout; |
4476 | 192 | return UGStatusSuccess; | 192 | return UGStatusSuccess; |
4477 | 193 | } | 193 | } |
4478 | 194 | } | 194 | |
4479 | 195 | 195 | case UGSubscriptionPropertyRotateThreshold: { | |
4480 | 196 | return UGStatusErrorUnknownProperty; | 196 | float threshold = *reinterpret_cast<const float*>(value); |
4481 | 197 | } | 197 | if (threshold < 0) |
4482 | 198 | 198 | return UGStatusErrorInvalidValue; | |
4483 | 199 | UGStatus UGSubscription_::GetProperty(UGSubscriptionProperty property, | 199 | d_->rotate_.threshold_ = threshold; |
4484 | 200 | void* value) const { | 200 | return UGStatusSuccess; |
4485 | 201 | switch (property) { | 201 | } |
4486 | 202 | case UGSubscriptionPropertyDevice: | 202 | |
4487 | 203 | *reinterpret_cast<UFDevice*>(value) = device_; | 203 | case UGSubscriptionPropertyTapTimeout: { |
4488 | 204 | return UGStatusSuccess; | 204 | uint64_t timeout = *reinterpret_cast<const uint64_t*>(value); |
4489 | 205 | 205 | if (timeout < 0) | |
4490 | 206 | case UGSubscriptionPropertyWindow: | 206 | return UGStatusErrorInvalidValue; |
4491 | 207 | *reinterpret_cast<Window*>(value) = window_; | 207 | d_->tap_.timeout_ = timeout; |
4492 | 208 | return UGStatusSuccess; | 208 | return UGStatusSuccess; |
4493 | 209 | 209 | } | |
4494 | 210 | case UGSubscriptionPropertyMask: | 210 | |
4495 | 211 | *reinterpret_cast<UGGestureTypeMask*>(value) = mask_; | 211 | case UGSubscriptionPropertyTapThreshold: { |
4496 | 212 | return UGStatusSuccess; | 212 | float threshold = *reinterpret_cast<const float*>(value); |
4497 | 213 | 213 | if (threshold < 0) | |
4498 | 214 | case UGSubscriptionPropertyTouchesStart: | 214 | return UGStatusErrorInvalidValue; |
4499 | 215 | *reinterpret_cast<unsigned int*>(value) = touches_start_; | 215 | d_->tap_.threshold_ = threshold; |
4500 | 216 | return UGStatusSuccess; | 216 | return UGStatusSuccess; |
4501 | 217 | 217 | } | |
4502 | 218 | case UGSubscriptionPropertyTouchesMinimum: | 218 | } |
4503 | 219 | *reinterpret_cast<unsigned int*>(value) = touches_min_; | 219 | |
4504 | 220 | return UGStatusSuccess; | 220 | return UGStatusErrorUnknownProperty; |
4505 | 221 | 221 | } | |
4506 | 222 | case UGSubscriptionPropertyTouchesMaximum: | 222 | |
4507 | 223 | *reinterpret_cast<unsigned int*>(value) = touches_max_; | 223 | UGStatus UGSubscription::GetProperty(UGSubscriptionProperty property, |
4508 | 224 | return UGStatusSuccess; | 224 | void* value) const { |
4509 | 225 | 225 | assert( value == NULL ); | |
4510 | 226 | case UGSubscriptionPropertyDragTimeout: | 226 | switch (property) { |
4511 | 227 | *reinterpret_cast<uint64_t*>(value) = drag_.timeout(); | 227 | case UGSubscriptionPropertyDevice: |
4512 | 228 | return UGStatusSuccess; | 228 | *reinterpret_cast<UFDevice*>(value) = d_->device_; |
4513 | 229 | 229 | return UGStatusSuccess; | |
4514 | 230 | case UGSubscriptionPropertyDragThreshold: | 230 | |
4515 | 231 | *reinterpret_cast<float*>(value) = drag_.threshold(); | 231 | case UGSubscriptionPropertyWindow: |
4516 | 232 | return UGStatusSuccess; | 232 | *reinterpret_cast<Window*>(value) = d_->window_; |
4517 | 233 | 233 | return UGStatusSuccess; | |
4518 | 234 | case UGSubscriptionPropertyPinchTimeout: | 234 | |
4519 | 235 | *reinterpret_cast<uint64_t*>(value) = pinch_.timeout(); | 235 | case UGSubscriptionPropertyMask: |
4520 | 236 | return UGStatusSuccess; | 236 | *reinterpret_cast<UGGestureTypeMask*>(value) = d_->mask_; |
4521 | 237 | 237 | return UGStatusSuccess; | |
4522 | 238 | case UGSubscriptionPropertyPinchThreshold: | 238 | |
4523 | 239 | *reinterpret_cast<float*>(value) = pinch_.threshold(); | 239 | case UGSubscriptionPropertyTouchesStart: |
4524 | 240 | return UGStatusSuccess; | 240 | *reinterpret_cast<unsigned int*>(value) = d_->touches_start_; |
4525 | 241 | 241 | return UGStatusSuccess; | |
4526 | 242 | case UGSubscriptionPropertyRotateTimeout: | 242 | |
4527 | 243 | *reinterpret_cast<uint64_t*>(value) = rotate_.timeout(); | 243 | case UGSubscriptionPropertyTouchesMinimum: |
4528 | 244 | return UGStatusSuccess; | 244 | *reinterpret_cast<unsigned int*>(value) = d_->touches_min_; |
4529 | 245 | 245 | return UGStatusSuccess; | |
4530 | 246 | case UGSubscriptionPropertyRotateThreshold: | 246 | |
4531 | 247 | *reinterpret_cast<float*>(value) = rotate_.threshold(); | 247 | case UGSubscriptionPropertyTouchesMaximum: |
4532 | 248 | return UGStatusSuccess; | 248 | *reinterpret_cast<unsigned int*>(value) = d_->touches_max_; |
4533 | 249 | 249 | return UGStatusSuccess; | |
4534 | 250 | case UGSubscriptionPropertyTapTimeout: | 250 | |
4535 | 251 | *reinterpret_cast<uint64_t*>(value) = tap_.timeout(); | 251 | case UGSubscriptionPropertyDragTimeout: |
4536 | 252 | return UGStatusSuccess; | 252 | *reinterpret_cast<uint64_t*>(value) = d_->drag_.timeout_; |
4537 | 253 | 253 | return UGStatusSuccess; | |
4538 | 254 | case UGSubscriptionPropertyTapThreshold: | 254 | |
4539 | 255 | *reinterpret_cast<float*>(value) = tap_.threshold(); | 255 | case UGSubscriptionPropertyDragThreshold: |
4540 | 256 | return UGStatusSuccess; | 256 | *reinterpret_cast<float*>(value) = d_->drag_.threshold_; |
4541 | 257 | } | 257 | return UGStatusSuccess; |
4542 | 258 | 258 | ||
4543 | 259 | return UGStatusErrorUnknownProperty; | 259 | case UGSubscriptionPropertyPinchTimeout: |
4544 | 260 | } | 260 | *reinterpret_cast<uint64_t*>(value) = d_->pinch_.timeout_; |
4545 | 261 | 261 | return UGStatusSuccess; | |
4546 | 262 | extern "C" { | 262 | |
4547 | 263 | 263 | case UGSubscriptionPropertyPinchThreshold: | |
4548 | 264 | UGStatus grail_subscription_new(UGSubscription* subscription) { | 264 | *reinterpret_cast<float*>(value) = d_->pinch_.threshold_; |
4549 | 265 | *subscription = new UGSubscription_; | 265 | return UGStatusSuccess; |
4550 | 266 | return UGStatusSuccess; | 266 | |
4551 | 267 | case UGSubscriptionPropertyRotateTimeout: | ||
4552 | 268 | *reinterpret_cast<uint64_t*>(value) = d_->rotate_.timeout_; | ||
4553 | 269 | return UGStatusSuccess; | ||
4554 | 270 | |||
4555 | 271 | case UGSubscriptionPropertyRotateThreshold: | ||
4556 | 272 | *reinterpret_cast<float*>(value) = d_->rotate_.threshold_; | ||
4557 | 273 | return UGStatusSuccess; | ||
4558 | 274 | |||
4559 | 275 | case UGSubscriptionPropertyTapTimeout: | ||
4560 | 276 | *reinterpret_cast<uint64_t*>(value) = d_->tap_.timeout_; | ||
4561 | 277 | return UGStatusSuccess; | ||
4562 | 278 | |||
4563 | 279 | case UGSubscriptionPropertyTapThreshold: | ||
4564 | 280 | *reinterpret_cast<float*>(value) = d_->tap_.threshold_; | ||
4565 | 281 | return UGStatusSuccess; | ||
4566 | 282 | } | ||
4567 | 283 | |||
4568 | 284 | return UGStatusErrorUnknownProperty; | ||
4569 | 285 | } | ||
4570 | 286 | |||
4571 | 287 | UFDevice UGSubscription::device() const { return d_->device_; } | ||
4572 | 288 | Window UGSubscription::window() const { return d_->window_; } | ||
4573 | 289 | UGGestureTypeMask UGSubscription::mask() const { return d_->mask_; } | ||
4574 | 290 | unsigned int UGSubscription::touches_start() const { return d_->touches_start_; } | ||
4575 | 291 | unsigned int UGSubscription::touches_min() const { return d_->touches_min_; } | ||
4576 | 292 | unsigned int UGSubscription::touches_max() const { return d_->touches_max_; } | ||
4577 | 293 | |||
4578 | 294 | const UGSubscription::Limit & UGSubscription::drag() const { return d_->drag_; } | ||
4579 | 295 | const UGSubscription::Limit & UGSubscription::pinch() const { return d_->pinch_; } | ||
4580 | 296 | const UGSubscription::Limit & UGSubscription::rotate() const { return d_->rotate_; } | ||
4581 | 297 | const UGSubscription::Limit & UGSubscription::tap() const { return d_->tap_; } | ||
4582 | 298 | } | ||
4583 | 299 | } | ||
4584 | 300 | // extern "C" { | ||
4585 | 301 | |||
4586 | 302 | UGStatus grail_subscription_new(UGSubscription * subscription) { | ||
4587 | 303 | *subscription = new UGSubscription(); | ||
4588 | 304 | return UGStatusSuccess; | ||
4589 | 267 | } | 305 | } |
4590 | 268 | 306 | ||
4591 | 269 | void grail_subscription_delete(UGSubscription subscription) { | 307 | void grail_subscription_delete(UGSubscription subscription) { |
4593 | 270 | delete subscription; | 308 | delete( static_cast< utouch::grail::UGSubscription* >( subscription ) ); |
4594 | 271 | } | 309 | } |
4595 | 272 | 310 | ||
4600 | 273 | UGStatus grail_subscription_set_property(UGSubscription subscription, | 311 | UGStatus grail_subscription_set_property( UGSubscription subscription, |
4601 | 274 | UGSubscriptionProperty property, | 312 | UGSubscriptionProperty property, |
4602 | 275 | const void* value) { | 313 | const void* value) { |
4603 | 276 | return subscription->SetProperty(property, value); | 314 | return( static_cast< utouch::grail::UGSubscription* >( subscription )->SetProperty(property, value ) ); |
4604 | 277 | } | 315 | } |
4605 | 278 | 316 | ||
4606 | 279 | UGStatus grail_subscription_get_property(UGSubscription subscription, | 317 | UGStatus grail_subscription_get_property(UGSubscription subscription, |
4607 | 280 | UGSubscriptionProperty property, | 318 | UGSubscriptionProperty property, |
4608 | 281 | void* value) { | 319 | void* value) { |
4610 | 282 | return subscription->GetProperty(property, value); | 320 | return( static_cast< utouch::grail::UGSubscription* >( subscription )->GetProperty(property, value) ); |
4611 | 283 | } | 321 | } |
4612 | 284 | 322 | ||
4614 | 285 | } // extern "C" | 323 | // } // extern "C" |
4615 | 286 | 324 | ||
4616 | === modified file 'src/v3/subscription.h' | |||
4617 | --- src/v3/subscription.h 2011-10-12 23:36:27 +0000 | |||
4618 | +++ src/v3/subscription.h 2011-11-01 21:20:40 +0000 | |||
4619 | @@ -26,58 +26,47 @@ | |||
4620 | 26 | 26 | ||
4621 | 27 | #include "utouch/grail.h" | 27 | #include "utouch/grail.h" |
4622 | 28 | 28 | ||
4677 | 29 | class Limit { | 29 | #include <memory> |
4678 | 30 | public: | 30 | |
4679 | 31 | explicit Limit(UGGestureType type); | 31 | namespace utouch { |
4680 | 32 | 32 | namespace grail { | |
4681 | 33 | uint64_t timeout() const { return timeout_; } | 33 | |
4682 | 34 | float threshold() const { return threshold_; } | 34 | class UGSubscription { |
4683 | 35 | 35 | public: | |
4684 | 36 | Limit(const Limit&) = delete; | 36 | |
4685 | 37 | void operator=(const Limit&) = delete; | 37 | struct Limit { |
4686 | 38 | 38 | explicit Limit( UGGestureType type ); | |
4687 | 39 | private: | 39 | |
4688 | 40 | void set_timeout(uint64_t timeout) { timeout_ = timeout; } | 40 | uint64_t timeout_; |
4689 | 41 | void set_threshold(float threshold) { threshold_ = threshold; } | 41 | float threshold_; |
4690 | 42 | uint64_t timeout_; | 42 | }; |
4691 | 43 | float threshold_; | 43 | |
4692 | 44 | 44 | UGSubscription(); | |
4693 | 45 | friend class UGSubscription_; | 45 | |
4694 | 46 | }; | 46 | bool IsValid() const; |
4695 | 47 | 47 | ||
4696 | 48 | class UGSubscription_ { | 48 | UGStatus SetProperty(UGSubscriptionProperty property, const void* value); |
4697 | 49 | public: | 49 | UGStatus GetProperty(UGSubscriptionProperty property, void* value) const; |
4698 | 50 | UGSubscription_(); | 50 | |
4699 | 51 | 51 | UFDevice device() const; | |
4700 | 52 | bool IsValid() const; | 52 | Window window() const; |
4701 | 53 | UGStatus SetProperty(UGSubscriptionProperty property, const void* value); | 53 | UGGestureTypeMask mask() const; |
4702 | 54 | UGStatus GetProperty(UGSubscriptionProperty property, void* value) const; | 54 | unsigned int touches_start() const; |
4703 | 55 | 55 | unsigned int touches_min() const; | |
4704 | 56 | UFDevice device() const { return device_; } | 56 | unsigned int touches_max() const; |
4705 | 57 | Window window() const { return window_; } | 57 | |
4706 | 58 | UGGestureTypeMask mask() const { return mask_; } | 58 | const Limit & drag() const; |
4707 | 59 | unsigned int touches_start() const { return touches_start_; } | 59 | const Limit & pinch() const; |
4708 | 60 | unsigned int touches_min() const { return touches_min_; } | 60 | const Limit & rotate() const; |
4709 | 61 | unsigned int touches_max() const { return touches_max_; } | 61 | const Limit & tap() const; |
4710 | 62 | const Limit& drag() const { return drag_; } | 62 | |
4711 | 63 | const Limit& pinch() const { return pinch_; } | 63 | UGSubscription(const UGSubscription & ) = delete; |
4712 | 64 | const Limit& rotate() const { return rotate_; } | 64 | UGSubscription & operator=(const UGSubscription & ) = delete; |
4713 | 65 | const Limit& tap() const { return tap_; } | 65 | |
4714 | 66 | 66 | protected: | |
4715 | 67 | UGSubscription_(const UGSubscription_&) = delete; | 67 | struct Private; |
4716 | 68 | void operator=(const UGSubscription_&) = delete; | 68 | std::shared_ptr< Private > d_; |
4717 | 69 | 69 | }; | |
4718 | 70 | private: | 70 | } |
4719 | 71 | UFDevice device_; | 71 | } |
4666 | 72 | Window window_; | ||
4667 | 73 | UGGestureTypeMask mask_; | ||
4668 | 74 | unsigned int touches_start_; | ||
4669 | 75 | unsigned int touches_min_; | ||
4670 | 76 | unsigned int touches_max_; | ||
4671 | 77 | Limit drag_; | ||
4672 | 78 | Limit pinch_; | ||
4673 | 79 | Limit rotate_; | ||
4674 | 80 | Limit tap_; | ||
4675 | 81 | }; | ||
4676 | 82 | |||
4720 | 83 | #endif // UTOUCH_GRAIL_SUBSCRIPTION_H_ | 72 | #endif // UTOUCH_GRAIL_SUBSCRIPTION_H_ |
src/v3/event.h:
(1) there is no need to namespace the class name since it is namespaced using a
namespace. "Event" should be fine.
(2) Inconsistent style: sometimes the reference modifier is separated from the
type name, sometimes not -- what does the team style guide say?
(3) why use a shared_ptr for the pimpl when copying the object is forbidden?
std::unique_ptr would be a better choice.
(4) is the tab style (mixed tab/spaces) consistent with the team style guidelines?
(5) Class documentation?
src/v3/gesture.h:
(1) why is <map> included?
(2) should utouch: :grail: :SharedUGDlice not be defined in the slice.h
header or be a member type?
(3) should utouch: :grail: :TouchSet not be defined in a touch header or be a
member type?
(4) do we really want to return a subscription by pointer?
(5) why use a shared_ptr for the pimpl when copying the object is forbidden?
std::unique_ptr would be a better choice.
src/v3/handle.h:
(1) why are <list> and <map> included? Why is <X11/X.h> included?
(2) there is no need to namespace the class name since it is namespaced using a
namespace. "Handle" should be fine.
(3) why use a shared_ptr for the pimpl when copying the object is forbidden?
std::unique_ptr would be a better choice.
(3) Inconsistent style: sometimes the pointer modifier is separated from the
type name, sometimes not, sometimes there is space after parentheses, sometimes
not -- what does the team style guide say?
src/v3/handle.cpp:
(1) Are the conditions passed to std::assert() reversed?
src/v3/ recognizer. h:
(1) why are <list> and <map> included?
(2) See points in other files regarding style and use of shared_ptr.
src/v3/ recognizer. cpp:
(1) I see a lot of raw Subscription pointers being passed around... should these
be wrapped in some kind of smart pointer?
src/v3/slice.h:
(1) See points in other files regarding namespacing, style and use of shared_ptr.
src/v3/slice.cpp:
(1) ::memcpy() is used but the required header is not included, <cstring>
provides std::memcpy()... std::copy_n() is probably a better choice anyway.
src/v3/ subscription. h:
(1) See points in other files regarding namespacing, style and use of shared_ptr.