Merge lp:~thomas-voss/grail/rework_cosmetics into lp:~chasedouglas/grail/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
Reviewer Review Type Date Requested Status
Stephen M. Webb (community) Needs Fixing
Chase Douglas Pending
Review via email: mp+80954@code.launchpad.net

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.
Revision history for this message
Stephen M. Webb (bregma) wrote :

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.

review: Needs Fixing

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
=== modified file 'include/utouch/grail.h'
--- include/utouch/grail.h 2011-10-19 21:39:17 +0000
+++ include/utouch/grail.h 2011-11-01 21:20:40 +0000
@@ -41,13 +41,13 @@
41 */41 */
4242
43/** An object for the context of the uTouch Frame instance */43/** An object for the context of the uTouch Frame instance */
44typedef struct UGHandle_* UGHandle;44typedef void * UGHandle;
45/** An object for a gesture subscription */45/** An object for a gesture subscription */
46typedef struct UGSubscription_* UGSubscription;46typedef void * UGSubscription;
47/** An object for an event */47/** An object for an event */
48typedef const struct UGEvent_* UGEvent;48typedef const void * UGEvent;
49/** An object for a gesture state in time */49/** An object for a gesture state in time */
50typedef const struct UGSlice_* UGSlice;50typedef void * UGSlice;
5151
52/** The status code denoting the result of a function call */52/** The status code denoting the result of a function call */
53typedef enum UGStatus {53typedef enum UGStatus {
@@ -400,7 +400,7 @@
400 * @param [out] event The retrieved event400 * @param [out] event The retrieved event
401 * @return UGStatusSuccess or UGStatusErrorNoEvent401 * @return UGStatusSuccess or UGStatusErrorNoEvent
402 */402 */
403UGStatus grail_get_event(UGHandle handle, UGEvent *event);403UGStatus grail_get_event(UGHandle handle, UGEvent * event );
404404
405/**405/**
406 * Release an event back to the uTouch Grail context406 * Release an event back to the uTouch Grail context
@@ -499,7 +499,7 @@
499 * @param [in] event The event object499 * @param [in] event The event object
500 * @return The type of the event500 * @return The type of the event
501 */501 */
502UGEventType grail_event_get_type(const UGEvent event);502UGEventType grail_event_get_type( UGEvent event);
503503
504/**504/**
505 * Get the time of an event505 * Get the time of an event
@@ -507,7 +507,7 @@
507 * @param [in] event The event object507 * @param [in] event The event object
508 * @return The time of the event508 * @return The time of the event
509 */509 */
510uint64_t grail_event_get_time(const UGEvent event);510uint64_t grail_event_get_time(UGEvent event);
511511
512/**512/**
513 * Get the ID of a gesture from a slice513 * Get the ID of a gesture from a slice
514514
=== modified file 'src/v3/event.cpp'
--- src/v3/event.cpp 2011-10-13 22:56:46 +0000
+++ src/v3/event.cpp 2011-11-01 21:20:40 +0000
@@ -1,6 +1,6 @@
1/*****************************************************************************1/*****************************************************************************
2 *2 *
3 * utouch-grail - Multitouch Gesture Recognition Library3 * Utouch-grail - Multitouch Gesture Recognition Library
4 *4 *
5 * Copyright (C) 2011 Canonical Ltd.5 * Copyright (C) 2011 Canonical Ltd.
6 *6 *
@@ -21,52 +21,71 @@
2121
22#include "event.h"22#include "event.h"
2323
24#include <assert.h>24#include <cassert>
2525
26#include "slice.h"26#include "slice.h"
2727
28UGEvent_::UGEvent_(const SharedUGSlice_& slice)28namespace utouch {
29 : slice_(slice),29 namespace grail {
30 time_(slice->time()) {30
31}31 struct UGEvent::Private {
3232
33UGStatus UGEvent_::GetProperty(UGEventProperty property, void* data) const {33 Private( const SharedUGSlice & slice ) : slice_( slice ),
34 switch (property) {34 time_( slice->time() ) {
35 case UGEventPropertyType:35 }
36 *reinterpret_cast<UGEventType*>(data) = UGEventTypeSlice;36
37 return UGStatusSuccess;37 const SharedUGSlice slice_;
3838 const uint64_t time_;
39 case UGEventPropertySlice:39 };
40 *reinterpret_cast<UGSlice*>(data) = slice_.get();40
41 return UGStatusSuccess;41 UGEvent::UGEvent(const SharedUGSlice & slice)
4242 : d_( new Private( slice ) ) {
43 case UGEventPropertyTime:43 }
44 *reinterpret_cast<uint64_t*>(data) = time_;44
45 return UGStatusSuccess;45 UGStatus UGEvent::GetProperty(UGEventProperty property, void* data) const {
46 }46 assert( data == NULL );
4747
48 return UGStatusErrorUnknownProperty;48 switch (property) {
49}49 case UGEventPropertyType:
5050 *reinterpret_cast<UGEventType*>(data) = UGEventTypeSlice;
51extern "C" {51 return UGStatusSuccess;
52
53 case UGEventPropertySlice:
54 *reinterpret_cast<UGSlice*>(data) = *d_->slice_.get();
55 return UGStatusSuccess;
56
57 case UGEventPropertyTime:
58 *reinterpret_cast<uint64_t*>(data) = d_->time_;
59 return UGStatusSuccess;
60 }
61
62 return UGStatusErrorUnknownProperty;
63 }
64 }
65
66}
5267
53UGStatus grail_event_get_property(const UGEvent event, UGEventProperty property,68UGStatus grail_event_get_property(const UGEvent event, UGEventProperty property,
54 void* data) {69 void* data) {
55 return event->GetProperty(property, data);70 assert( event == NULL );
71 assert( data == NULL );
72
73 return static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(property, data);
56}74}
5775
58UGEventType grail_event_get_type(const UGEvent event) {76UGEventType grail_event_get_type(const UGEvent event) {
59 UGEventType type;77 assert( event == NULL );
60 UGStatus status = event->GetProperty(UGEventPropertyType, &type);78 UGEventType type;
61 assert(status == UGStatusSuccess);79 UGStatus status = static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(UGEventPropertyType, &type);
62 return type;80 assert(status == UGStatusSuccess);
81 return type;
63}82}
6483
65uint64_t grail_event_get_time(const UGEvent event) {84uint64_t grail_event_get_time(const UGEvent event) {
66 uint64_t time;85 assert( event == NULL );
67 UGStatus status = event->GetProperty(UGEventPropertyTime, &time);86 uint64_t time;
68 assert(status == UGStatusSuccess);87 UGStatus status = static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(UGEventPropertyTime, &time);
69 return time;88 assert(status == UGStatusSuccess);
89 return time;
70}90}
7191
72} // extern "C"
7392
=== modified file 'src/v3/event.h'
--- src/v3/event.h 2011-10-13 22:56:46 +0000
+++ src/v3/event.h 2011-11-01 21:20:40 +0000
@@ -24,26 +24,31 @@
2424
25#include <memory>25#include <memory>
2626
27#include <stdint.h>27#include <cstdint>
2828
29#include "utouch/grail.h"29#include "utouch/grail.h"
3030
31class UGSlice_;31namespace utouch {
3232 namespace grail {
33typedef std::shared_ptr<UGSlice_> SharedUGSlice_;33
3434 class UGSlice;
35class UGEvent_ {35
36 public:36 typedef std::shared_ptr<UGSlice> SharedUGSlice;
37 UGEvent_(const SharedUGSlice_& slice);37
3838 class UGEvent {
39 UGStatus GetProperty(UGEventProperty property, void* value) const;39 public:
4040 UGEvent(const SharedUGSlice & slice);
41 UGEvent_(const UGEvent_&) = delete;41
42 void operator=(const UGEvent_&) = delete;42 UGStatus GetProperty(UGEventProperty property, void* value) const;
4343
44 private:44 UGEvent(const UGEvent&) = delete;
45 const SharedUGSlice_ slice_;45 void operator=(const UGEvent&) = delete;
46 const uint64_t time_;46
47};47 protected:
4848 struct Private;
49 std::shared_ptr< Private > d_;
50
51 };
52 }
53}
49#endif // UTOUCH_GRAIL_EVENT_H54#endif // UTOUCH_GRAIL_EVENT_H
5055
=== modified file 'src/v3/gesture.cpp'
--- src/v3/gesture.cpp 2011-10-20 22:19:11 +0000
+++ src/v3/gesture.cpp 2011-11-01 21:20:40 +0000
@@ -21,7 +21,7 @@
2121
22#include "gesture.h"22#include "gesture.h"
2323
24#include <stdio.h>24#include <cstdio>
2525
26#include "utouch/grail.h"26#include "utouch/grail.h"
2727
@@ -30,184 +30,249 @@
30#include "recognizer.h"30#include "recognizer.h"
31#include "slice.h"31#include "slice.h"
3232
33Gesture::Gesture(Recognizer* recognizer, UGSubscription_* subscription,33namespace utouch {
34 TouchSet& touches, uint64_t start_time)34 namespace grail {
35 : recognizer_(recognizer),35
36 id_(recognizer_->handle()->NewGestureID(recognizer_)),36 struct Gesture::Private {
37 subscription_(subscription),37
38 touches_(touches),38 Private( Recognizer * recognizer,
39 start_time_(start_time),39 utouch::grail::UGSubscription * subscription,
40 recognized_(0),40 TouchSet & touches,
41 canceled_(false),41 uint64_t start_time )
42 ended_(false) {42 : recognizer_(recognizer),
43}43 id_(recognizer_->handle()->NewGestureID(recognizer_)),
4444 subscription_(subscription),
45Gesture::Gesture(const Gesture* other_gesture, TouchSet& touches)45 touches_(touches),
46 : recognizer_(other_gesture->recognizer_),46 start_time_(start_time),
47 id_(recognizer_->handle()->NewGestureID(recognizer_)),47 recognized_(0),
48 subscription_(other_gesture->subscription_),48 canceled_(false),
49 touches_(touches),49 ended_(false) {
50 start_time_(other_gesture->start_time_),50 }
51 recognized_(other_gesture->recognized_),51
52 canceled_(false),52 Private( const Gesture* other_gesture, TouchSet & touches )
53 ended_(false) {53 : recognizer_(other_gesture->d_->recognizer_),
54}54 id_(recognizer_->handle()->NewGestureID(recognizer_)),
5555 subscription_(other_gesture->d_->subscription_),
56void Gesture::Update(UFEvent frame_event, TouchSet& modified_touches) {56 touches_(touches),
57 if (ended_) {57 start_time_(other_gesture->d_->start_time_),
58 if (recognized_ && IsOwned())58 recognized_(other_gesture->d_->recognized_),
59 FlushSlices();59 canceled_(false),
6060 ended_(false) {
61 return;61 }
62 }62
6363 Recognizer * recognizer_;
64 UFFrame frame;64 unsigned int id_;
65 UFStatus status = frame_event_get_property(frame_event, UFEventPropertyFrame,65 utouch::grail::UGSubscription* subscription_;
66 &frame);66 TouchSet touches_;
67 if (status != UFStatusSuccess) {67 uint64_t start_time_;
68 fprintf(stderr, "Warning: failed to get frame from event\n");68 UGGestureTypeMask recognized_;
69 return;69 std::queue<utouch::grail::SharedUGSlice> slices_;
70 }70 utouch::grail::SharedUGSlice last_slice_;
7171 bool canceled_;
72 TouchSet ended_touches;72 bool ended_;
73 bool touch_found = false;73 std::map<unsigned int, float> angles_;
74 for (unsigned int touch_id : modified_touches) {74 };
75 if (touches_.find(touch_id) != touches_.end())75
76 touch_found = true;76 Gesture::Gesture(Recognizer* recognizer, utouch::grail::UGSubscription* subscription,
77 else77 TouchSet& touches, uint64_t start_time)
78 continue;78 : d_( new Private( recognizer, subscription, touches, start_time ) ) {
7979 }
80 UFTouch touch;80
81 status = frame_frame_get_touch_by_id(frame, &touch_id, &touch);81 Gesture::Gesture(const Gesture* other_gesture, TouchSet& touches)
82 if (status != UFStatusSuccess) {82 : d_( new Private( other_gesture, touches ) ) {
83 fprintf(stderr, "Warning: failed to get touch from frame\n");83 }
84 return;84
85 }85 void Gesture::Update(UFEvent frame_event, TouchSet& modified_touches) {
8686 if ( d_->ended_) {
87 UFTouchState state = frame_touch_get_state(touch);87 if (d_->recognized_ && IsOwned())
88 int owned;88 FlushSlices();
89 status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned);89
90 if (status != UFStatusSuccess) {90 return;
91 fprintf(stderr, "Warning: failed to get touch from frame\n");91 }
92 return;92
93 }93 UFFrame frame;
9494 UFStatus status = frame_event_get_property(frame_event, UFEventPropertyFrame,
95 if (state == UFTouchStateEnd) {95 &frame);
96 if (owned) {96 if (status != UFStatusSuccess) {
97 ended_touches.insert(touch_id);97 fprintf(stderr, "Warning: failed to get frame from event\n");
98 } else {98 return;
99 canceled_ = true;99 }
100 break;100
101 }101 TouchSet ended_touches;
102 }102 bool touch_found = false;
103 }103 for (unsigned int touch_id : modified_touches) {
104104 if (d_->touches_.find(touch_id) != d_->touches_.end())
105 if (!touch_found || canceled_)105 touch_found = true;
106 return;106 else
107107 continue;
108 if (!last_slice_) {108
109 UGSlice_* slice = UGSlice_::NewUGSlice_(shared_from_this(), frame_event,109 UFTouch touch;
110 touches_, recognized_);110 status = frame_frame_get_touch_by_id(frame, &touch_id, &touch);
111 if (!slice)111 if (status != UFStatusSuccess) {
112 return;112 fprintf(stderr, "Warning: failed to get touch from frame\n");
113 last_slice_ = SharedUGSlice_(slice);113 return;
114 } else {114 }
115 UGSlice_* slice = UGSlice_::NewUGSlice_(last_slice_, frame_event, touches_);115
116 if (!slice)116 UFTouchState state = frame_touch_get_state(touch);
117 return;117 int owned;
118 last_slice_ = SharedUGSlice_(slice);118 status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned);
119 }119 if (status != UFStatusSuccess) {
120120 fprintf(stderr, "Warning: failed to get touch from frame\n");
121 slices_.push(last_slice_);121 return;
122122 }
123 for (unsigned int touch_id : ended_touches)123
124 touches_.erase(touch_id);124 if (state == UFTouchStateEnd) {
125125 if (owned) {
126 if (recognized_ != subscription_->mask())126 ended_touches.insert(touch_id);
127 recognized_ |= last_slice_->CheckRecognition(*subscription_);127 } else {
128128 d_->canceled_ = true;
129 if (recognized_ && IsOwned())129 break;
130 FlushSlices();130 }
131131 }
132 ended_ = (last_slice_->state() == UGGestureStateEnd);132 }
133 if (ended_)133
134 last_slice_.reset();134 if (!touch_found || d_->canceled_)
135}135 return;
136136
137bool Gesture::IsOwned() const {137 /* TODO
138 /* The only way we could reach here and not have any slices in the queue is138 if (!last_slice_) {
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(),
140 */140 frame_event,
141 if (slices_.empty())141 touches_,
142 return true;142 recognized_
143143 );
144 for (unsigned int touch_id : slices_.front()->touches()) {144
145 UFTouch touch;145 if (!slice)
146 UFStatus status = frame_frame_get_touch_by_id(slices_.back()->frame(),146 return;
147 &touch_id, &touch);147 last_slice_ = utouch::grail::SharedUGSlice(slice);
148 if (status != UFStatusSuccess) {148 } else {
149 fprintf(stderr, "Warning: failed to get touch from frame\n");149 // TODO
150 return false;150 // utouch::grail::UGSlice * slice = utouch::grail::UGSlice::NewUGSlice(last_slice_, frame_event, touches_);
151 }151 if (!slice)
152152 return;
153 int owned;153 last_slice_ = utouch::grail::SharedUGSlice(slice);
154 status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned);154 }*/
155 if (status != UFStatusSuccess) {155
156 fprintf(stderr, "Warning: failed to get ownership property from touch\n");156 d_->slices_.push(d_->last_slice_);
157 return false;157
158 }158 for (unsigned int touch_id : ended_touches)
159159 d_->touches_.erase(touch_id);
160 if (!owned)160
161 return false;161 if ( d_->recognized_ != d_->subscription_->mask())
162 }162 d_->recognized_ |= d_->last_slice_->CheckRecognition(*d_->subscription_);
163163
164 return true;164 if (d_->recognized_ && IsOwned())
165}165 FlushSlices();
166166
167void Gesture::FlushSlices() {167 d_->ended_ = (d_->last_slice_->state() == UGGestureStateEnd);
168 while (!slices_.empty()) {168 if (d_->ended_)
169 UGEvent_* event = new UGEvent_(slices_.front());169 d_->last_slice_.reset();
170 slices_.front()->ReferenceGesture();170 }
171 recognizer_->handle()->EnqueueEvent(event);171
172 slices_.pop();172 bool Gesture::IsOwned() const {
173 }173 /* The only way we could reach here and not have any slices in the queue is
174}174 * if we already flushed the queue, which is only done if we own the touches.
175175 */
176uint64_t Gesture::Timeout() const {176 if (d_->slices_.empty())
177 if (recognized_)177 return true;
178 return 0;178
179179 for (unsigned int touch_id : d_->slices_.front()->touches()) {
180 uint64_t time = 0;180 UFTouch touch;
181 if ((subscription_->mask() & UGGestureTypeDrag) &&181 UFStatus status = frame_frame_get_touch_by_id(d_->slices_.back()->frame(),
182 subscription_->drag().timeout() > time)182 &touch_id, &touch);
183 time = subscription_->drag().timeout();183 if (status != UFStatusSuccess) {
184 if ((subscription_->mask() & UGGestureTypePinch) &&184 fprintf(stderr, "Warning: failed to get touch from frame\n");
185 subscription_->pinch().timeout() > time)185 return false;
186 time = subscription_->pinch().timeout();186 }
187 if ((subscription_->mask() & UGGestureTypeRotate) &&187
188 subscription_->rotate().timeout() > time)188 int owned;
189 time = subscription_->rotate().timeout();189 status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned);
190 if ((subscription_->mask() & UGGestureTypeTap) &&190 if (status != UFStatusSuccess) {
191 subscription_->tap().timeout() > time)191 fprintf(stderr, "Warning: failed to get ownership property from touch\n");
192 time = subscription_->tap().timeout();192 return false;
193193 }
194 return time;194
195}195 if (!owned)
196196 return false;
197float Gesture::AngleForTouch(unsigned int touch_id) const {197 }
198 auto it = angles_.find(touch_id);198
199 if (it != angles_.end())199 return true;
200 return it->second;200 }
201201
202 return 0;202 void Gesture::FlushSlices() {
203}203 while (!d_->slices_.empty()) {
204204 utouch::grail::UGEvent * event = new utouch::grail::UGEvent(d_->slices_.front());
205void Gesture::SetAngleForTouch(unsigned int touch_id, float angle) {205 d_->slices_.front()->ReferenceGesture();
206 angles_[touch_id] = angle;206 d_->recognizer_->handle()->EnqueueEvent(event);
207}207 d_->slices_.pop();
208208 }
209void Gesture::Cancel() {209 }
210 while (!slices_.empty())210
211 slices_.pop();211 uint64_t Gesture::Timeout() const {
212 last_slice_.reset();212 if (d_->recognized_)
213 return 0;
214
215 uint64_t time = 0;
216 if ((d_->subscription_->mask() & UGGestureTypeDrag) &&
217 d_->subscription_->drag().timeout_ > time)
218 time = d_->subscription_->drag().timeout_;
219 if ((d_->subscription_->mask() & UGGestureTypePinch) &&
220 d_->subscription_->pinch().timeout_ > time)
221 time = d_->subscription_->pinch().timeout_;
222 if ((d_->subscription_->mask() & UGGestureTypeRotate) &&
223 d_->subscription_->rotate().timeout_ > time)
224 time = d_->subscription_->rotate().timeout_;
225 if ((d_->subscription_->mask() & UGGestureTypeTap) &&
226 d_->subscription_->tap().timeout_ > time)
227 time = d_->subscription_->tap().timeout_;
228
229 return time;
230 }
231
232 float Gesture::AngleForTouch(unsigned int touch_id) const {
233 auto it = d_->angles_.find(touch_id);
234 if (it != d_->angles_.end())
235 return it->second;
236
237 return 0;
238 }
239
240 void Gesture::SetAngleForTouch(unsigned int touch_id, float angle) {
241 d_->angles_[touch_id] = angle;
242 }
243
244 void Gesture::Cancel() {
245 while (!d_->slices_.empty())
246 d_->slices_.pop();
247 d_->last_slice_.reset();
248 }
249
250 const unsigned int Gesture::id() const {
251 return d_->id_;
252 }
253
254 const Recognizer & Gesture::recognizer() const {
255 return *d_->recognizer_;
256 }
257
258 utouch::grail::UGSubscription* Gesture::subscription() const {
259 return d_->subscription_;
260 }
261
262 const TouchSet& Gesture::touches() const {
263 return d_->touches_;
264 }
265
266 const uint64_t Gesture::start_time() const {
267 return d_->start_time_;
268 }
269
270 bool Gesture::canceled() const {
271 return d_->canceled_;
272 }
273
274 bool Gesture::ended() const {
275 return d_->ended_;
276 }
277 }
213}278}
214279
=== modified file 'src/v3/gesture.h'
--- src/v3/gesture.h 2011-10-20 22:19:11 +0000
+++ src/v3/gesture.h 2011-11-01 21:20:40 +0000
@@ -31,49 +31,46 @@
3131
32#include "utouch/grail.h"32#include "utouch/grail.h"
3333
34class Recognizer;34namespace utouch {
35class UGSlice_;35 namespace grail {
3636 class Recognizer;
37typedef std::shared_ptr<UGSlice_> SharedUGSlice_;37
38typedef std::set<unsigned int> TouchSet;38 class UGSubscription;
3939 class UGSlice;
40class Gesture : public std::enable_shared_from_this<Gesture> {40 typedef std::shared_ptr<UGSlice> SharedUGSlice;
41 public:41
42 Gesture(Recognizer* recognizer, UGSubscription_* subscription,42 typedef std::set<unsigned int> TouchSet;
43 TouchSet& touches, uint64_t start_time);43
44 Gesture(const Gesture* gesture, TouchSet& touches);44 class Gesture : public std::enable_shared_from_this<Gesture> {
4545 public:
46 void Update(UFEvent event, TouchSet& touches);46 Gesture(Recognizer* recognizer, utouch::grail::UGSubscription* subscription,
47 bool IsOwned() const;47 TouchSet& touches, uint64_t start_time);
48 void FlushSlices();48 Gesture(const Gesture* gesture, TouchSet& touches);
49 uint64_t Timeout() const;49
50 float AngleForTouch(unsigned int touch_id) const;50 void Update(UFEvent event, TouchSet& touches);
51 void SetAngleForTouch(unsigned int touch_id, float angle);51 bool IsOwned() const;
52 void Cancel();52 void FlushSlices();
5353 uint64_t Timeout() const;
54 const unsigned int id() const { return id_; }54 float AngleForTouch(unsigned int touch_id) const;
55 const Recognizer& recognizer() const { return *recognizer_; }55 void SetAngleForTouch(unsigned int touch_id, float angle);
56 UGSubscription_* subscription() const { return subscription_; }56 void Cancel();
57 const TouchSet& touches() const { return touches_; }57
58 const uint64_t start_time() const { return start_time_; }58 const unsigned int id() const;
59 bool canceled() const { return canceled_; }59 const Recognizer& recognizer() const;
60 bool ended() const { return ended_; }60 utouch::grail::UGSubscription* subscription() const;
6161 const TouchSet& touches() const;
62 Gesture(const Gesture&) = delete;62 const uint64_t start_time() const;
63 void operator=(const Gesture&) = delete;63 bool canceled() const;
6464 bool ended() const;
65 private:65
66 Recognizer* recognizer_;66 Gesture(const Gesture&) = delete;
67 unsigned int id_;67 void operator=(const Gesture&) = delete;
68 UGSubscription_* subscription_;68
69 TouchSet touches_;69 private:
70 uint64_t start_time_;70 struct Private;
71 UGGestureTypeMask recognized_;71 std::shared_ptr< Private > d_;
72 std::queue<SharedUGSlice_> slices_;72 };
73 SharedUGSlice_ last_slice_;73
74 bool canceled_;74 }
75 bool ended_;75}
76 std::map<unsigned int, float> angles_;
77};
78
79#endif // UTOUCH_GRAIL_GESTURE_H_76#endif // UTOUCH_GRAIL_GESTURE_H_
8077
=== modified file 'src/v3/handle.cpp'
--- src/v3/handle.cpp 2011-10-19 22:06:43 +0000
+++ src/v3/handle.cpp 2011-11-01 21:20:40 +0000
@@ -21,9 +21,9 @@
2121
22#include "v3/handle.h"22#include "v3/handle.h"
2323
24#include <assert.h>24#include <cassert>
25#include <errno.h>25#include <cerrno>
26#include <stdio.h>26#include <cstdio>
27#include <sys/eventfd.h>27#include <sys/eventfd.h>
28#include <unistd.h>28#include <unistd.h>
2929
@@ -33,315 +33,347 @@
3333
34#include "v3/event.h"34#include "v3/event.h"
35#include "v3/recognizer.h"35#include "v3/recognizer.h"
36#include "v3/slice.h"
36#include "v3/subscription.h"37#include "v3/subscription.h"
3738
38UGHandle_::UGHandle_(UFHandle frame_handle)39namespace utouch {
39 : frame_handle_(frame_handle),40 namespace grail {
40 event_fd_(-1),41
41 next_id_(0) {42 struct UGHandle::Private {
42}43
4344 Private( UFHandle frame_handle )
44UGStatus UGHandle_::Initialize() {45 : frame_handle_(frame_handle),
45 event_fd_ = eventfd(0, EFD_NONBLOCK);46 event_fd_(-1),
46 if (event_fd_ == -1) {47 next_id_(0) {
47 fprintf(stderr, "Error: failed to create eventfd instance\n");48 }
48 return UGStatusErrorResources;49
49 }50 typedef std::unique_ptr<Recognizer> UniqueRecognizer;
5051
51 return UGStatusSuccess;52 const UFHandle frame_handle_;
52}53 int event_fd_;
5354 unsigned int next_id_;
54UGHandle_* UGHandle_::NewUGHandle_(UFHandle frame_handle) {55 std::map<UFDevice, std::map<Window, UniqueRecognizer>> recognizers_;
55 UGHandle_* handle = new UGHandle_(frame_handle);56 std::map<unsigned int, Recognizer*> gestures_;
56 if (handle->Initialize() != UGStatusSuccess) {57 std::list<utouch::grail::UGEvent*> event_queue_;
57 delete handle;58
58 return NULL;59 UGStatus Initialize() {
59 }60 event_fd_ = eventfd(0, EFD_NONBLOCK);
6061 if (event_fd_ == -1) {
61 return handle;62 fprintf(stderr, "Error: failed to create eventfd instance\n");
62}63 return UGStatusErrorResources;
6364 }
64UGStatus UGHandle_::ActivateSubscription(UGSubscription_* subscription) {65
65 Recognizer* recognizer;66 return UGStatusSuccess;
6667 }
67 if (!subscription->IsValid())68 };
68 return UGStatusErrorInvalidSubscription;69
6970
70 const auto& it =71 UGHandle::UGHandle(UFHandle frame_handle)
71 recognizers_[subscription->device()].find(subscription->window());72 : d_( new Private( frame_handle ) ) {
72 if (it != recognizers_[subscription->device()].end()) {73 }
73 recognizer = it->second.get();74
74 } else {75 int UGHandle::event_fd() const {
75 recognizer = new Recognizer(this, subscription->device(),76 return( d_->event_fd_ );
76 subscription->window());77 }
77 recognizers_[subscription->device()][subscription->window()] =78
78 std::move(UniqueRecognizer(recognizer));79 UGStatus UGHandle::ActivateSubscription( utouch::grail::UGSubscription * subscription) {
79 }80 Recognizer* recognizer;
8081
81 recognizer->ActivateSubscription(subscription);82 if (!subscription->IsValid())
8283 return UGStatusErrorInvalidSubscription;
83 return UGStatusSuccess;84
84}85 const auto& it =
8586 d_->recognizers_[subscription->device()].find(subscription->window());
86void UGHandle_::DeactivateSubscription(UGSubscription_* subscription) {87 if (it != d_->recognizers_[subscription->device()].end()) {
87 recognizers_[subscription->device()].erase(subscription->window());88 recognizer = it->second.get();
88}89 } else {
8990 recognizer = new Recognizer(this, subscription->device(),
90namespace {91 subscription->window());
9192 d_->recognizers_[subscription->device()][subscription->window()] =
92bool GetDeviceFromEvent(const UFEvent event, UFDevice* device) {93 std::move( Private::UniqueRecognizer( recognizer ) );
93 UFStatus status = frame_event_get_property(event, UFEventPropertyDevice,94 }
94 device);95
95 if (status != UFStatusSuccess) {96 recognizer->ActivateSubscription( subscription );
96 fprintf(stderr, "Warning: failed to get device from event\n");97
97 return false;98 return UGStatusSuccess;
98 }99 }
99100
100 return true;101 void UGHandle::DeactivateSubscription( utouch::grail::UGSubscription * subscription) {
101}102 d_->recognizers_[subscription->device()].erase(subscription->window());
102103 }
103bool GetDeviceAndWindowFromEvent(const UFEvent event, UFDevice* device,104
104 Window* window) {105 namespace {
105 UFFrame frame;106
106 UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,107 bool GetDeviceFromEvent(const UFEvent event, UFDevice* device) {
107 &frame);108 UFStatus status = frame_event_get_property( event,
108 if (status != UFStatusSuccess) {109 UFEventPropertyDevice,
109 fprintf(stderr, "Warning: failed to get frame from event\n");110 device);
110 return false;111 if (status != UFStatusSuccess) {
111 }112 fprintf(stderr, "Warning: failed to get device from event\n");
112113 return false;
113 *device = frame_frame_get_device(frame);114 }
114115
115 status = frame_frame_get_property(frame, UFFramePropertyWindow, window);116 return true;
116 if (status != UFStatusSuccess) {117 }
117 fprintf(stderr, "Warning: failed to get window from frame\n");118
118 return false;119 bool GetDeviceAndWindowFromEvent(const UFEvent event, UFDevice* device,
119 }120 Window* window) {
120121 UFFrame frame;
121 return true;122 UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
122}123 &frame);
123124 if (status != UFStatusSuccess) {
124void RejectFrame(const UFEvent event, const UFDevice device, Window window) {125 fprintf(stderr, "Warning: failed to get frame from event\n");
125 UFFrame frame;126 return false;
126 UFStatus status;127 }
127 unsigned int num_touches;128
128 unsigned int i;129 *device = frame_frame_get_device(frame);
129130
130 status = frame_event_get_property(event, UFEventPropertyFrame, &frame);131 status = frame_frame_get_property(frame, UFFramePropertyWindow, window);
131 if (status != UFStatusSuccess) {132 if (status != UFStatusSuccess) {
132 fprintf(stderr, "Warning: failed to get frame from event\n");133 fprintf(stderr, "Warning: failed to get window from frame\n");
133 return;134 return false;
134 }135 }
135136
136 num_touches = frame_frame_get_num_touches(frame);137 return true;
137138 }
138 for (i = 0; i < num_touches; ++i) {139
139 UFTouch touch;140 void RejectFrame(const UFEvent event, const UFDevice device, Window window) {
140 unsigned int touch_id;141 UFFrame frame;
141142 UFStatus status;
142 status = frame_frame_get_touch_by_index(frame, i, &touch);143 unsigned int num_touches;
143 if (status != UFStatusSuccess) {144 unsigned int i;
144 fprintf(stderr, "Warning: failed to get touch from frame by index\n");145
145 continue;146 status = frame_event_get_property(event, UFEventPropertyFrame, &frame);
146 }147 if (status != UFStatusSuccess) {
147148 fprintf(stderr, "Warning: failed to get frame from event\n");
148 if (frame_touch_get_state(touch) != UFTouchStateBegin)149 return;
149 continue;150 }
150151
151 status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);152 num_touches = frame_frame_get_num_touches(frame);
152 if (status != UFStatusSuccess) {153
153 fprintf(stderr, "Warning: failed to get touch ID from touch\n");154 for (i = 0; i < num_touches; ++i) {
154 continue;155 UFTouch touch;
155 }156 unsigned int touch_id;
156157
157 frame_x11_reject_touch(device, window, touch_id);158 status = frame_frame_get_touch_by_index(frame, i, &touch);
158 }159 if (status != UFStatusSuccess) {
159}160 fprintf(stderr, "Warning: failed to get touch from frame by index\n");
160161 continue;
161} // namespace162 }
162163
163void UGHandle_::ProcessFrameEvent(const UFEvent event) {164 if (frame_touch_get_state(touch) != UFTouchStateBegin)
164 switch (frame_event_get_type(event)) {165 continue;
165 case UFEventTypeDeviceAdded: {166
166 UFDevice device;167 status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
167 if (!GetDeviceFromEvent(event, &device))168 if (status != UFStatusSuccess) {
168 return;169 fprintf(stderr, "Warning: failed to get touch ID from touch\n");
169 recognizers_.insert(std::make_pair(device,170 continue;
170 std::map<Window, UniqueRecognizer>()));171 }
171 break;172
172 }173 frame_x11_reject_touch(device, window, touch_id);
173174 }
174 case UFEventTypeDeviceRemoved: {175 }
175 UFDevice device;176
176 if (!GetDeviceFromEvent(event, &device))177 } // namespace
177 return;178
178 recognizers_.erase(device);179 void UGHandle::ProcessFrameEvent(const UFEvent event) {
179 break;180 switch (frame_event_get_type(event)) {
180 }181 case UFEventTypeDeviceAdded: {
181182 UFDevice device;
182 case UFEventTypeFrame: {183 if (!GetDeviceFromEvent(event, &device))
183 UFDevice device;184 return;
184 Window window;185 d_->recognizers_.insert(std::make_pair(device,
185 if (!GetDeviceAndWindowFromEvent(event, &device, &window))186 std::map<Window, Private::UniqueRecognizer>()));
186 return;187 break;
187188 }
188 if (recognizers_[device].find(window) != recognizers_[device].end())189
189 recognizers_[device][window]->ProcessFrameEvent(event);190 case UFEventTypeDeviceRemoved: {
190 else191 UFDevice device;
191 RejectFrame(event, device, window);192 if (!GetDeviceFromEvent(event, &device))
192193 return;
193 break;194 d_->recognizers_.erase(device);
194 }195 break;
195 }196 }
196}197
197198 case UFEventTypeFrame: {
198void UGHandle_::UpdateTime(uint64_t time) {199 UFDevice device;
199 for (auto& pair : recognizers_)200 Window window;
200 for (auto& pair2 : pair.second)201 if (!GetDeviceAndWindowFromEvent(event, &device, &window))
201 pair2.second->UpdateTime(time);202 return;
202}203
203204 if (d_->recognizers_[device].find(window) != d_->recognizers_[device].end())
204unsigned int UGHandle_::NewGestureID(Recognizer* recognizer) {205 d_->recognizers_[device][window]->ProcessFrameEvent(event);
205 unsigned int id = next_id_++;206 else
206 gestures_[id] = recognizer;207 RejectFrame(event, device, window);
207 return id;208
208}209 break;
209210 }
210void UGHandle_::EnqueueEvent(const UGEvent_* event) {211 }
211 static const uint64_t num = 1;212 }
212213
213 event_queue_.push_back(event);214 void UGHandle::UpdateTime(uint64_t time) {
214 if (write(event_fd_, &num, sizeof(num)) != sizeof(num))215 for (auto& pair : d_->recognizers_)
215 fprintf(stderr, "Warning: failed to update eventfd instance\n");216 for (auto& pair2 : pair.second)
216}217 pair2.second->UpdateTime(time);
217218 }
218void UGHandle_::RemoveGestureFromEventQueue(unsigned int id) {219
219 for (auto it = event_queue_.begin(); it != event_queue_.end(); ) {220 unsigned int UGHandle::NewGestureID(Recognizer* recognizer) {
220 const UGEvent_* event = *it++;221 unsigned int id = d_->next_id_++;
221 if (grail_event_get_type(event) != UGEventTypeSlice)222 d_->gestures_[id] = recognizer;
222 continue;223 return id;
223224 }
224 UGSlice slice;225
225 UGStatus status = grail_event_get_property(event, UGEventPropertySlice,226 void UGHandle::EnqueueEvent(utouch::grail::UGEvent * event) {
226 &slice);227 static const uint64_t num = 1;
227 assert(status == UGStatusSuccess);228
228229 d_->event_queue_.push_back(event);
229 if (grail_slice_get_id(slice) == id) {230 if (write(d_->event_fd_, &num, sizeof(num)) != sizeof(num))
230 event_queue_.remove(event);231 fprintf(stderr, "Warning: failed to update eventfd instance\n");
231 ReleaseEvent(event);232 }
232 }233
233 }234 void UGHandle::RemoveGestureFromEventQueue(unsigned int id) {
234}235 for (auto it = d_->event_queue_.begin(); it != d_->event_queue_.end(); ) {
235236 utouch::grail::UGEvent * event = *it++;
236UGStatus UGHandle_::GetEvent(const UGEvent_** event) {237 if (grail_event_get_type(event) != UGEventTypeSlice)
237 /* Clear event fd (see eventfd(2) man page) */238 continue;
238 uint64_t buf;239
239 if (read(event_fd_, &buf, sizeof(buf)) != 8 && errno != EAGAIN)240 void * slice;
240 fprintf(stderr, "Warning: failed to read data from event fd\n");241 UGStatus status = grail_event_get_property( event,
241242 UGEventPropertySlice,
242 if (event_queue_.empty())243 &slice);
243 return UGStatusErrorNoEvent;244 assert(status == UGStatusSuccess);
244245
245 *event = event_queue_.front();246 if (grail_slice_get_id(slice) == id) {
246 event_queue_.pop_front();247 d_->event_queue_.remove(event);
247248 ReleaseEvent(event);
248 return UGStatusSuccess;249 }
249}250 }
250251 }
251void UGHandle_::ReleaseEvent(const UGEvent_* event) {252
252 delete event;253 UGStatus UGHandle::GetEvent( const utouch::grail::UGEvent ** event) {
253}254 /* Clear event fd (see eventfd(2) man page) */
254255 uint64_t buf;
255uint64_t UGHandle_::NextTimeout() const {256 if( read(d_->event_fd_, &buf, sizeof(buf) ) != 8 && errno != EAGAIN)
256 uint64_t min_timeout = std::numeric_limits<uint64_t>::max();257 fprintf(stderr, "Warning: failed to read data from event fd\n");
257 for (auto& pair : recognizers_) {258
258 for (auto& pair2 : pair.second) {259 if (d_->event_queue_.empty())
259 uint64_t timeout = pair2.second->NextTimeout();260 return UGStatusErrorNoEvent;
260 if (timeout < min_timeout)261
261 min_timeout = timeout;262 *event = d_->event_queue_.front();
262 }263 d_->event_queue_.pop_front();
263 }264
264265 return UGStatusSuccess;
265 return min_timeout != std::numeric_limits<uint64_t>::max() ? min_timeout : 0;266 }
266}267
267268 void UGHandle::ReleaseEvent(const utouch::grail::UGEvent * event) {
268UGStatus UGHandle_::AcceptGesture(unsigned int id) {269 delete event;
269 auto it = gestures_.find(id);270 }
270 if (it == gestures_.end())271
271 return UGStatusErrorInvalidGesture;272 uint64_t UGHandle::NextTimeout() const {
272273 uint64_t min_timeout = std::numeric_limits<uint64_t>::max();
273 return it->second->AcceptGesture(id);274 for (auto& pair : d_->recognizers_) {
274}275 for (auto& pair2 : pair.second) {
275276 uint64_t timeout = pair2.second->NextTimeout();
276UGStatus UGHandle_::RejectGesture(unsigned int id) {277 if (timeout < min_timeout)
277 auto it = gestures_.find(id);278 min_timeout = timeout;
278 if (it == gestures_.end())279 }
279 return UGStatusErrorInvalidGesture;280 }
280281
281 return it->second->RejectGesture(id);282 return min_timeout != std::numeric_limits<uint64_t>::max() ? min_timeout : 0;
282}283 }
283284
284UGHandle_::~UGHandle_() {285 UGStatus UGHandle::AcceptGesture(unsigned int id) {
285 while (!event_queue_.empty()) {286 auto it = d_->gestures_.find(id);
286 ReleaseEvent(event_queue_.front());287 if (it == d_->gestures_.end())
287 event_queue_.pop_front();288 return UGStatusErrorInvalidGesture;
288 }289
289}290 return it->second->AcceptGesture(id);
290291 }
291extern "C" {292
292293 UGStatus UGHandle::RejectGesture(unsigned int id) {
293UGStatus grail_new(UFHandle frame_handle, UGHandle* handle) {294 auto it = d_->gestures_.find(id);
294 *handle = UGHandle_::NewUGHandle_(frame_handle);295 if (it == d_->gestures_.end())
295 if (!*handle)296 return UGStatusErrorInvalidGesture;
296 return UGStatusErrorResources;297
297298 return it->second->RejectGesture(id);
298 return UGStatusSuccess;299 }
299}300
300301 UGHandle::~UGHandle() {
301void grail_delete_v3(UGHandle handle) {302 while (!d_->event_queue_.empty()) {
302 delete handle;303 ReleaseEvent(d_->event_queue_.front());
303}304 d_->event_queue_.pop_front();
304305 }
305int grail_get_fd(UGHandle handle) {306 }
306 return handle->event_fd();307 }
307}308
308309 utouch::grail::UGHandle * utouch::grail::UGHandle::NewUGHandle( UFHandle frame_handle ) {
309UGStatus grail_subscription_activate(UGHandle handle,310 utouch::grail::UGHandle * handle = new utouch::grail::UGHandle(frame_handle);
310 const UGSubscription subscription) {311 if( handle->d_->Initialize() != UGStatusSuccess ) {
311 return handle->ActivateSubscription(subscription);312 delete handle;
312}313 return NULL;
313314 }
314void grail_subscription_deactivate(UGHandle handle,315
315 const UGSubscription subscription) {316 return handle;
316 return handle->DeactivateSubscription(subscription);317 }
317}318
318319 UGStatus grail_new(UFHandle frame_handle, UGHandle* handle) {
319void grail_process_frame_event(UGHandle handle, const UFEvent event) {320 assert( handle == NULL );
320 handle->ProcessFrameEvent(event);321 *handle = utouch::grail::UGHandle::NewUGHandle(frame_handle);
321}322 if (!*handle)
322323 return UGStatusErrorResources;
323UGStatus grail_get_event(UGHandle handle, UGEvent *event) {324
324 return handle->GetEvent(event);325 return UGStatusSuccess;
325}326 }
326327
327void grail_release_event(UGHandle handle, UGEvent event) {328 void grail_delete_v3(UGHandle handle) {
328 handle->ReleaseEvent(event);329 assert( handle == NULL );
329}330 delete( static_cast< utouch::grail::UGHandle* >( handle ) );
330331 }
331void grail_update_time(UGHandle handle, uint64_t time) {332
332 handle->UpdateTime(time);333 int grail_get_fd(UGHandle handle) {
333}334 assert( handle == NULL );
334335 return static_cast< utouch::grail::UGHandle* >( handle )->event_fd();
335uint64_t grail_next_timeout(UGHandle handle) {336 }
336 return handle->NextTimeout();337
337}338 UGStatus grail_subscription_activate(UGHandle handle,
338339 const UGSubscription subscription) {
339UGStatus grail_accept_gesture(UGHandle handle, unsigned int id) {340 assert( handle == NULL );
340 return handle->AcceptGesture(id);341 return static_cast< utouch::grail::UGHandle* >( handle )->ActivateSubscription(static_cast< utouch::grail::UGSubscription* >( subscription ) );
341}342 }
342343
343UGStatus grail_reject_gesture(UGHandle handle, unsigned int id) {344 void grail_subscription_deactivate(UGHandle handle,
344 return handle->RejectGesture(id);345 const UGSubscription subscription) {
345}346 assert( handle == NULL );
346347 return static_cast< utouch::grail::UGHandle* >( handle )->DeactivateSubscription( static_cast< utouch::grail::UGSubscription* >( subscription ) );
347} // extern "C"348 }
349
350 void grail_process_frame_event(UGHandle handle, const UFEvent event) {
351 assert( handle == NULL );
352 static_cast< utouch::grail::UGHandle* >( handle )->ProcessFrameEvent( event );
353 }
354
355 UGStatus grail_get_event(UGHandle handle, UGEvent *event) {
356 const utouch::grail::UGEvent * uge = static_cast< const utouch::grail::UGEvent* >( *event );
357 return static_cast< utouch::grail::UGHandle* >( handle )->GetEvent( &uge );
358 }
359
360 void grail_release_event(UGHandle handle, UGEvent event) {
361 static_cast< utouch::grail::UGHandle* >( handle )->ReleaseEvent( static_cast< const utouch::grail::UGEvent* >( event ) );
362 }
363
364 void grail_update_time(UGHandle handle, uint64_t time) {
365 static_cast< utouch::grail::UGHandle* >( handle )->UpdateTime(time);
366 }
367
368 uint64_t grail_next_timeout(UGHandle handle) {
369 return static_cast< utouch::grail::UGHandle* >( handle )->NextTimeout();
370 }
371
372 UGStatus grail_accept_gesture(UGHandle handle, unsigned int id) {
373 return static_cast< utouch::grail::UGHandle* >( handle )->AcceptGesture(id);
374 }
375
376 UGStatus grail_reject_gesture(UGHandle handle, unsigned int id) {
377 return static_cast< utouch::grail::UGHandle* >( handle )->RejectGesture(id);
378 }
379}
348380
=== modified file 'src/v3/handle.h'
--- src/v3/handle.h 2011-10-18 21:35:48 +0000
+++ src/v3/handle.h 2011-11-01 21:20:40 +0000
@@ -31,44 +31,43 @@
3131
32#include "utouch/grail.h"32#include "utouch/grail.h"
3333
34class Recognizer;34namespace utouch {
35class UGEvent_;35 namespace grail {
3636
37class UGHandle_ {37 class Recognizer;
38 public:38
39 static UGHandle_* NewUGHandle_(UFHandle frame_handle);39 class UGEvent;
4040 class UGSubscription;
41 ~UGHandle_();41
4242 class UGHandle {
43 int event_fd() const { return event_fd_; }43 public:
44 UGStatus ActivateSubscription(UGSubscription_* subscription);44 static UGHandle* NewUGHandle(UFHandle frame_handle);
45 void DeactivateSubscription(UGSubscription_* subscription);45
46 unsigned int NewGestureID(Recognizer* recognizer);46 ~UGHandle();
47 void ProcessFrameEvent(UFEvent event);47
48 void UpdateTime(uint64_t time);48 int event_fd() const;
49 uint64_t NextTimeout() const;49 UGStatus ActivateSubscription( utouch::grail::UGSubscription* subscription);
50 void EnqueueEvent(const UGEvent_*);50 void DeactivateSubscription( utouch::grail::UGSubscription* subscription);
51 void RemoveGestureFromEventQueue(unsigned int id);51 unsigned int NewGestureID(Recognizer* recognizer);
52 UGStatus GetEvent(const UGEvent_** event);52 void ProcessFrameEvent(UFEvent event);
53 void ReleaseEvent(const UGEvent_* event);53 void UpdateTime(uint64_t time);
54 UGStatus AcceptGesture(unsigned int id);54 uint64_t NextTimeout() const;
55 UGStatus RejectGesture(unsigned int id);55 void EnqueueEvent(utouch::grail::UGEvent * );
5656 void RemoveGestureFromEventQueue(unsigned int id);
57 UGHandle_(const UGHandle_&) = delete;57 UGStatus GetEvent( const utouch::grail::UGEvent ** event );
58 void operator=(const UGHandle_&) = delete;58 void ReleaseEvent(const utouch::grail::UGEvent * event);
5959 UGStatus AcceptGesture(unsigned int id);
60 private:60 UGStatus RejectGesture(unsigned int id);
61 typedef std::unique_ptr<Recognizer> UniqueRecognizer;61
6262 UGHandle(const UGHandle&) = delete;
63 const UFHandle frame_handle_;63 void operator=(const UGHandle&) = delete;
64 int event_fd_;64
65 unsigned int next_id_;65 protected:
66 std::map<UFDevice, std::map<Window, UniqueRecognizer>> recognizers_;66 struct Private;
67 std::map<unsigned int, Recognizer*> gestures_;67 std::shared_ptr< Private > d_;
68 std::list<const UGEvent_*> event_queue_;68
6969 UGHandle(UFHandle frame_handle);
70 UGHandle_(UFHandle frame_handle);70 };
71 UGStatus Initialize();71 }
72};72}
73
74#endif // UTOUCH_GRAIL_HANDLE_H_73#endif // UTOUCH_GRAIL_HANDLE_H_
7574
=== modified file 'src/v3/recognizer.cpp'
--- src/v3/recognizer.cpp 2011-10-19 22:07:30 +0000
+++ src/v3/recognizer.cpp 2011-11-01 21:20:40 +0000
@@ -21,8 +21,8 @@
2121
22#include "v3/recognizer.h"22#include "v3/recognizer.h"
2323
24#include <stdint.h>24#include <cstdint>
25#include <stdio.h>25#include <cstdio>
2626
27#include <algorithm>27#include <algorithm>
28#include <limits>28#include <limits>
@@ -35,492 +35,541 @@
3535
36namespace {36namespace {
3737
38const uint64_t kCompositionTime = 60;38 const uint64_t kCompositionTime = 60;
3939
40} // namespace40 void GetModifiedAndEndedTouches(UFFrame frame, utouch::grail::TouchSet* modified,
4141 utouch::grail::TouchSet* ended, uint64_t event_time) {
42Recognizer::Recognizer(UGHandle_* handle, const UFDevice device, Window window)42 unsigned int num_touches = frame_frame_get_num_touches(frame);
43 : handle_(handle),43 for (unsigned int i = 0; i < num_touches; ++i) {
44 device_(device),44 UFTouch touch;
45 window_(window),45 UFStatus status = frame_frame_get_touch_by_index(frame, i, &touch);
46 device_x_res_(46), /* Default to resolution of Apple Magic Trackpad */46 if (status != UFStatusSuccess) {
47 device_y_res_(45),47 fprintf(stderr, "Warning: failed to get touch from frame\n");
48 device_direct_(true) {48 continue;
49 UFAxis axis;49 }
50 UFStatus status = frame_device_get_axis_by_type(device, UFAxisTypeX, &axis);50
51 if (status != UFStatusSuccess)51 if (frame_touch_get_time(touch) == event_time) {
52 fprintf(stderr, "Warning: failed to get X axis from device\n");52 unsigned int touch_id;
53 else53 status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
54 device_x_res_ = frame_axis_get_resolution(axis);54 if (status != UFStatusSuccess) {
5555 fprintf(stderr, "Warning: failed to get touch id from touch\n");
56 status = frame_device_get_axis_by_type(device, UFAxisTypeY, &axis);56 continue;
57 if (status != UFStatusSuccess)57 }
58 fprintf(stderr, "Warning: failed to get Y axis from device\n");58
59 else59 modified->insert(touch_id);
60 device_y_res_ = frame_axis_get_resolution(axis);60
6161 if (frame_touch_get_state(touch) == UFTouchStateEnd)
62 status = frame_device_get_property(device, UFDevicePropertyDirect,62 ended->insert(touch_id);
63 &device_direct_);63 }
64 if (status != UFStatusSuccess)64 }
65 fprintf(stderr,65 }
66 "Warning: failed to get direct property value for device\n");66
67}67} // namespace
6868
69void Recognizer::ActivateSubscription(UGSubscription_* subscription) {69namespace utouch {
70 subscriptions_[subscription->touches_start() - 1].insert(subscription);70 namespace grail {
71}71
7272 struct Recognizer::Private {
73void Recognizer::DeactivateSubscription(UGSubscription_* subscription) {73
74 subscriptions_[subscription->touches_start() - 1].erase(subscription);74 Private( Recognizer * parent, utouch::grail::UGHandle * handle, const UFDevice device, Window window)
7575 : parent_( parent ),
76 for (auto it = unaccepted_gestures_.begin();76 handle_(handle),
77 it != unaccepted_gestures_.end();77 device_(device),
78 ) {78 window_(window),
79 const SharedGesture& gesture = *it++;79 device_x_res_(46), /* Default to resolution of Apple Magic Trackpad */
80 if (gesture->subscription() == subscription)80 device_y_res_(45),
81 gesture->Cancel();81 device_direct_(true) {
82 unaccepted_gestures_.erase(gesture);82 UFAxis axis;
83 }83 UFStatus status = frame_device_get_axis_by_type(device, UFAxisTypeX, &axis);
8484 if (status != UFStatusSuccess)
85 for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) {85 fprintf(stderr, "Warning: failed to get X axis from device\n");
86 const SharedGesture& gesture = *it++;86 else
87 if (gesture->subscription() == subscription)87 device_x_res_ = frame_axis_get_resolution(axis);
88 gesture->Cancel();88
89 accepted_gestures_.erase(gesture);89 status = frame_device_get_axis_by_type(device, UFAxisTypeY, &axis);
90 }90 if (status != UFStatusSuccess)
91}91 fprintf(stderr, "Warning: failed to get Y axis from device\n");
9292 else
93void Recognizer::ProcessFrameEvent(const UFEvent event) {93 device_y_res_ = frame_axis_get_resolution(axis);
94 UpdateTime(frame_event_get_time(event));94
95 MatchSubscriptionsForEvent(event);95 status = frame_device_get_property( device,
96 ProcessEvent(event);96 UFDevicePropertyDirect,
97}97 &device_direct_);
9898 if (status != UFStatusSuccess)
99void Recognizer::MatchSubscriptionsForEvent(const UFEvent event) {99 fprintf(stderr,
100 bool active_subscriptions = false;100 "Warning: failed to get direct property value for device\n");
101 for (auto subscriptions : subscriptions_) {101 }
102 if (!subscriptions.empty()) {102
103 active_subscriptions = true;103 void MatchSubscriptionsForEvent(const UFEvent event) {
104 break;104 bool active_subscriptions = false;
105 }105 for (auto subscriptions : subscriptions_) {
106 }106 if (!subscriptions.empty()) {
107 if (!active_subscriptions)107 active_subscriptions = true;
108 return;108 break;
109109 }
110 UFFrame frame;110 }
111 UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,111 if (!active_subscriptions)
112 &frame);112 return;
113 if (status != UFStatusSuccess) {113
114 fprintf(stderr, "Warning: failed to get frame from event\n");114 UFFrame frame;
115 return;115 UFStatus status = frame_event_get_property( event,
116 }116 UFEventPropertyFrame,
117117 &frame);
118 unsigned int num_touches = frame_frame_get_num_touches(frame);118 if (status != UFStatusSuccess) {
119 for (unsigned int i = 0; i < num_touches; ++i) {119 fprintf(stderr, "Warning: failed to get frame from event\n");
120 UFTouch touch;120 return;
121 status = frame_frame_get_touch_by_index(frame, i, &touch);121 }
122 if (status != UFStatusSuccess) {122
123 fprintf(stderr, "Warning: failed to get touch from frame\n");123 unsigned int num_touches = frame_frame_get_num_touches(frame);
124 continue;124 for (unsigned int i = 0; i < num_touches; ++i) {
125 }125 UFTouch touch;
126126 status = frame_frame_get_touch_by_index(frame, i, &touch);
127 unsigned int touch_id;127 if (status != UFStatusSuccess) {
128 status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);128 fprintf(stderr, "Warning: failed to get touch from frame\n");
129 if (status != UFStatusSuccess) {129 continue;
130 fprintf(stderr, "Warning: failed to get touch id from touch\n");130 }
131 continue;131
132 }132 unsigned int touch_id;
133133 status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
134 switch (frame_touch_get_state(touch)) {134 if (status != UFStatusSuccess) {
135 case UFTouchStateBegin: {135 fprintf(stderr, "Warning: failed to get touch id from touch\n");
136 start_times_[touch_id] = frame_touch_get_start_time(touch);136 continue;
137 unaccepted_touches_.insert(touch_id);137 }
138 free_touches_.insert(touch_id);138
139139 switch (frame_touch_get_state(touch)) {
140 for (const SharedGesture& gesture : accepted_gestures_) {140 case UFTouchStateBegin: {
141 UGSubscription_* subscription = gesture->subscription();141 start_times_[touch_id] = frame_touch_get_start_time(touch);
142 if (gesture->touches().size() < subscription->touches_max()) {142 unaccepted_touches_.insert(touch_id);
143 TouchSet set(gesture->touches());143 free_touches_.insert(touch_id);
144 set.insert(touch_id);144
145 Gesture* new_gesture = new Gesture(gesture.get(), set);145 for (const utouch::grail::SharedGesture & gesture : accepted_gestures_) {
146 unaccepted_gestures_.insert(SharedGesture(new_gesture));146 utouch::grail::UGSubscription * subscription = gesture->subscription();
147 }147 if (gesture->touches().size() < subscription->touches_max()) {
148 }148 TouchSet set(gesture->touches());
149149 set.insert(touch_id);
150 for (const SharedGesture& gesture : unaccepted_gestures_) {150 utouch::grail::Gesture* new_gesture = new utouch::grail::Gesture(gesture.get(), set);
151 UGSubscription_* subscription = gesture->subscription();151 unaccepted_gestures_.insert(utouch::grail::SharedGesture(new_gesture));
152 if (gesture->touches().size() < subscription->touches_max()) {152 }
153 TouchSet set(gesture->touches());153 }
154 set.insert(touch_id);154
155 Gesture* new_gesture = new Gesture(gesture.get(), set);155 for (const utouch::grail::SharedGesture & gesture : unaccepted_gestures_) {
156 unaccepted_gestures_.insert(SharedGesture(new_gesture));156 utouch::grail::UGSubscription* subscription = gesture->subscription();
157 }157 if (gesture->touches().size() < subscription->touches_max()) {
158 }158 TouchSet set(gesture->touches());
159159 set.insert(touch_id);
160 MatchOneTouchGestures(touch_id);160 utouch::grail::Gesture * new_gesture = new utouch::grail::Gesture(gesture.get(), set);
161 MatchTwoTouchGestures(touch_id);161 unaccepted_gestures_.insert( utouch::grail::SharedGesture(new_gesture));
162 MatchThreeTouchGestures(touch_id);162 }
163 MatchFourTouchGestures(touch_id);163 }
164 MatchFiveTouchGestures(touch_id);164
165 break;165 MatchOneTouchGestures(touch_id);
166 }166 MatchTwoTouchGestures(touch_id);
167167 MatchThreeTouchGestures(touch_id);
168 default:168 MatchFourTouchGestures(touch_id);
169 break;169 MatchFiveTouchGestures(touch_id);
170 }170 break;
171 }171 }
172}172
173173 default:
174void Recognizer::MatchOneTouchGestures(unsigned int touch_id) {174 break;
175 for (UGSubscription_* subscription : subscriptions_[0]) {175 }
176 TouchSet set;176 }
177 set.insert(touch_id);177 }
178 Gesture* gesture = new Gesture(this, subscription, set,178
179 start_times_[touch_id]);179 void MatchOneTouchGestures(unsigned int touch_id) {
180 unaccepted_gestures_.insert(SharedGesture(gesture));180 for( utouch::grail::UGSubscription* subscription : subscriptions_[0] ) {
181 }181 TouchSet set;
182}182 set.insert(touch_id);
183183 utouch::grail::Gesture* gesture = new utouch::grail::Gesture( parent_,
184void Recognizer::MatchTwoTouchGestures(unsigned int touch_id) {184 subscription, set,
185 for (UGSubscription_* subscription : subscriptions_[1]) {185 start_times_[touch_id]);
186 for (unsigned int other_id : free_touches_) {186 unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture));
187 if (other_id == touch_id)187 }
188 continue;188 }
189189
190 uint64_t min_start_time = start_times_[touch_id];190 void MatchTwoTouchGestures(unsigned int touch_id) {
191 if (start_times_[other_id] < min_start_time &&191 for( utouch::grail::UGSubscription* subscription : subscriptions_[1] ) {
192 unaccepted_touches_.find(other_id) != unaccepted_touches_.end())192 for (unsigned int other_id : free_touches_) {
193 min_start_time = start_times_[other_id];193 if (other_id == touch_id)
194194 continue;
195 if (start_times_[touch_id] - min_start_time < kCompositionTime) {195
196 TouchSet set;196 uint64_t min_start_time = start_times_[touch_id];
197 set.insert(touch_id);197 if (start_times_[other_id] < min_start_time &&
198 set.insert(other_id);198 unaccepted_touches_.find(other_id) != unaccepted_touches_.end())
199 Gesture* gesture = new Gesture(this, subscription, set,199 min_start_time = start_times_[other_id];
200 start_times_[touch_id]);200
201 unaccepted_gestures_.insert(SharedGesture(gesture));201 if (start_times_[touch_id] - min_start_time < kCompositionTime) {
202 }202 TouchSet set;
203 }203 set.insert(touch_id);
204 }204 set.insert(other_id);
205}205 utouch::grail::Gesture* gesture = new utouch::grail::Gesture(parent_, subscription, set,
206206 start_times_[touch_id]);
207void Recognizer::MatchThreeTouchGestures(unsigned int touch_id) {207 unaccepted_gestures_.insert( utouch::grail::SharedGesture(gesture) );
208 for (UGSubscription_* subscription : subscriptions_[2]) {208 }
209 for (unsigned int other_id_1 : free_touches_) {209 }
210 if (other_id_1 == touch_id)210 }
211 continue;211 }
212212
213 for (unsigned int other_id_2 : free_touches_) {213 void MatchThreeTouchGestures(unsigned int touch_id) {
214 if (other_id_2 == touch_id || other_id_2 == other_id_1)214 for( utouch::grail::UGSubscription* subscription : subscriptions_[2] ) {
215 continue;215 for (unsigned int other_id_1 : free_touches_) {
216216 if (other_id_1 == touch_id)
217 uint64_t min_start_time = start_times_[touch_id];217 continue;
218 if (start_times_[other_id_1] < min_start_time &&218
219 unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end())219 for (unsigned int other_id_2 : free_touches_) {
220 min_start_time = start_times_[other_id_1];220 if (other_id_2 == touch_id || other_id_2 == other_id_1)
221 if (start_times_[other_id_2] < min_start_time &&221 continue;
222 unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end())222
223 min_start_time = start_times_[other_id_2];223 uint64_t min_start_time = start_times_[touch_id];
224224 if (start_times_[other_id_1] < min_start_time &&
225 if (start_times_[touch_id] - min_start_time < kCompositionTime) {225 unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end())
226 TouchSet set;226 min_start_time = start_times_[other_id_1];
227 set.insert(touch_id);227 if (start_times_[other_id_2] < min_start_time &&
228 set.insert(other_id_1);228 unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end())
229 set.insert(other_id_2);229 min_start_time = start_times_[other_id_2];
230 Gesture* gesture = new Gesture(this, subscription, set,230
231 start_times_[touch_id]);231 if (start_times_[touch_id] - min_start_time < kCompositionTime) {
232 unaccepted_gestures_.insert(SharedGesture(gesture));232 TouchSet set;
233 }233 set.insert(touch_id);
234 }234 set.insert(other_id_1);
235 }235 set.insert(other_id_2);
236 }236 utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_, subscription, set,
237}237 start_times_[touch_id]);
238238 unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture));
239void Recognizer::MatchFourTouchGestures(unsigned int touch_id) {239 }
240 for (UGSubscription_* subscription : subscriptions_[3]) {240 }
241 for (unsigned int other_id_1 : free_touches_) {241 }
242 if (other_id_1 == touch_id)242 }
243 continue;243 }
244244
245 for (unsigned int other_id_2 : free_touches_) {245 void MatchFourTouchGestures(unsigned int touch_id) {
246 if (other_id_2 == touch_id || other_id_2 == other_id_1)246 for( utouch::grail::UGSubscription* subscription : subscriptions_[3] ) {
247 continue;247 for (unsigned int other_id_1 : free_touches_) {
248248 if (other_id_1 == touch_id)
249 for (unsigned int other_id_3 : free_touches_) {249 continue;
250 if (other_id_3 == touch_id || other_id_3 == other_id_1 ||250
251 other_id_3 == other_id_2)251 for (unsigned int other_id_2 : free_touches_) {
252 continue;252 if (other_id_2 == touch_id || other_id_2 == other_id_1)
253253 continue;
254 uint64_t min_start_time = start_times_[touch_id];254
255 if (start_times_[other_id_1] < min_start_time &&255 for (unsigned int other_id_3 : free_touches_) {
256 unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end())256 if (other_id_3 == touch_id || other_id_3 == other_id_1 ||
257 min_start_time = start_times_[other_id_1];257 other_id_3 == other_id_2)
258 if (start_times_[other_id_2] < min_start_time &&258 continue;
259 unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end())259
260 min_start_time = start_times_[other_id_2];260 uint64_t min_start_time = start_times_[touch_id];
261 if (start_times_[other_id_3] < min_start_time &&261 if (start_times_[other_id_1] < min_start_time &&
262 unaccepted_touches_.find(other_id_3) != unaccepted_touches_.end())262 unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end())
263 min_start_time = start_times_[other_id_3];263 min_start_time = start_times_[other_id_1];
264264 if (start_times_[other_id_2] < min_start_time &&
265 if (start_times_[touch_id] - min_start_time < kCompositionTime) {265 unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end())
266 TouchSet set;266 min_start_time = start_times_[other_id_2];
267 set.insert(touch_id);267 if (start_times_[other_id_3] < min_start_time &&
268 set.insert(other_id_1);268 unaccepted_touches_.find(other_id_3) != unaccepted_touches_.end())
269 set.insert(other_id_2);269 min_start_time = start_times_[other_id_3];
270 set.insert(other_id_3);270
271 Gesture* gesture = new Gesture(this, subscription, set,271 if (start_times_[touch_id] - min_start_time < kCompositionTime) {
272 start_times_[touch_id]);272 TouchSet set;
273 unaccepted_gestures_.insert(SharedGesture(gesture));273 set.insert(touch_id);
274 }274 set.insert(other_id_1);
275 }275 set.insert(other_id_2);
276 }276 set.insert(other_id_3);
277 }277 utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_,
278 }278 subscription,
279}279 set,
280280 start_times_[touch_id]);
281void Recognizer::MatchFiveTouchGestures(unsigned int touch_id) {281 unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture));
282 for (UGSubscription_* subscription : subscriptions_[4]) {282 }
283 for (unsigned int other_id_1 : free_touches_) {283 }
284 if (other_id_1 == touch_id)284 }
285 continue;285 }
286286 }
287 for (unsigned int other_id_2 : free_touches_) {287 }
288 if (other_id_2 == touch_id || other_id_2 == other_id_1)288
289 continue;289 void MatchFiveTouchGestures(unsigned int touch_id) {
290290 for (utouch::grail::UGSubscription* subscription : subscriptions_[4]) {
291 for (unsigned int other_id_3 : free_touches_) {291 for (unsigned int other_id_1 : free_touches_) {
292 if (other_id_3 == touch_id || other_id_3 == other_id_1 ||292 if (other_id_1 == touch_id)
293 other_id_3 == other_id_2)293 continue;
294 continue;294
295295 for (unsigned int other_id_2 : free_touches_) {
296 for (unsigned int other_id_4 : free_touches_) {296 if (other_id_2 == touch_id || other_id_2 == other_id_1)
297 if (other_id_4 == touch_id || other_id_4 == other_id_1 ||297 continue;
298 other_id_4 == other_id_2 || other_id_4 == other_id_3)298
299 continue;299 for (unsigned int other_id_3 : free_touches_) {
300300 if (other_id_3 == touch_id || other_id_3 == other_id_1 ||
301 uint64_t min_start_time = start_times_[touch_id];301 other_id_3 == other_id_2)
302 if (start_times_[other_id_1] < min_start_time &&302 continue;
303 unaccepted_touches_.find(other_id_1) !=303
304 unaccepted_touches_.end())304 for (unsigned int other_id_4 : free_touches_) {
305 min_start_time = start_times_[other_id_1];305 if (other_id_4 == touch_id || other_id_4 == other_id_1 ||
306 if (start_times_[other_id_2] < min_start_time &&306 other_id_4 == other_id_2 || other_id_4 == other_id_3)
307 unaccepted_touches_.find(other_id_2) !=307 continue;
308 unaccepted_touches_.end())308
309 min_start_time = start_times_[other_id_2];309 uint64_t min_start_time = start_times_[touch_id];
310 if (start_times_[other_id_3] < min_start_time &&310 if (start_times_[other_id_1] < min_start_time &&
311 unaccepted_touches_.find(other_id_3) !=311 unaccepted_touches_.find(other_id_1) !=
312 unaccepted_touches_.end())312 unaccepted_touches_.end())
313 min_start_time = start_times_[other_id_3];313 min_start_time = start_times_[other_id_1];
314 if (start_times_[other_id_4] < min_start_time &&314 if (start_times_[other_id_2] < min_start_time &&
315 unaccepted_touches_.find(other_id_4) !=315 unaccepted_touches_.find(other_id_2) !=
316 unaccepted_touches_.end())316 unaccepted_touches_.end())
317 min_start_time = start_times_[other_id_4];317 min_start_time = start_times_[other_id_2];
318318 if (start_times_[other_id_3] < min_start_time &&
319 if (start_times_[touch_id] - min_start_time < kCompositionTime) {319 unaccepted_touches_.find(other_id_3) !=
320 TouchSet set;320 unaccepted_touches_.end())
321 set.insert(touch_id);321 min_start_time = start_times_[other_id_3];
322 set.insert(other_id_1);322 if (start_times_[other_id_4] < min_start_time &&
323 set.insert(other_id_2);323 unaccepted_touches_.find(other_id_4) !=
324 set.insert(other_id_3);324 unaccepted_touches_.end())
325 set.insert(other_id_4);325 min_start_time = start_times_[other_id_4];
326 Gesture* gesture = new Gesture(this, subscription, set,326
327 start_times_[touch_id]);327 if (start_times_[touch_id] - min_start_time < kCompositionTime) {
328 unaccepted_gestures_.insert(SharedGesture(gesture));328 TouchSet set;
329 }329 set.insert(touch_id);
330 }330 set.insert(other_id_1);
331 }331 set.insert(other_id_2);
332 }332 set.insert(other_id_3);
333 }333 set.insert(other_id_4);
334 }334 utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_, subscription, set,
335}335 start_times_[touch_id]);
336336 unaccepted_gestures_.insert( utouch::grail::SharedGesture(gesture) );
337namespace {337 }
338338 }
339void GetModifiedAndEndedTouches(UFFrame frame, TouchSet* modified,339 }
340 TouchSet* ended, uint64_t event_time) {340 }
341 unsigned int num_touches = frame_frame_get_num_touches(frame);341 }
342 for (unsigned int i = 0; i < num_touches; ++i) {342 }
343 UFTouch touch;343 }
344 UFStatus status = frame_frame_get_touch_by_index(frame, i, &touch);344
345 if (status != UFStatusSuccess) {345 void ProcessEvent(const UFEvent& event) {
346 fprintf(stderr, "Warning: failed to get touch from frame\n");346 UFFrame frame;
347 continue;347 UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
348 }348 &frame);
349349 if (status != UFStatusSuccess) {
350 if (frame_touch_get_time(touch) == event_time) {350 fprintf(stderr, "Warning: failed to get frame from event\n");
351 unsigned int touch_id;351 return;
352 status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);352 }
353 if (status != UFStatusSuccess) {353
354 fprintf(stderr, "Warning: failed to get touch id from touch\n");354 TouchSet modified_touches;
355 continue;355 TouchSet ended_touches;
356 }356 GetModifiedAndEndedTouches(frame, &modified_touches,
357357 &ended_touches, frame_event_get_time(event));
358 modified->insert(touch_id);358
359359 for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) {
360 if (frame_touch_get_state(touch) == UFTouchStateEnd)360 const utouch::grail::SharedGesture & gesture = *it++;
361 ended->insert(touch_id);361 gesture->Update(event, modified_touches);
362 }362 if (gesture->ended()) {
363 }363 for (unsigned int touch_id : gesture->touches())
364}364 free_touches_.insert(touch_id);
365365 accepted_gestures_.erase(gesture);
366} // namespace366 }
367367 }
368void Recognizer::ProcessEvent(const UFEvent& event) {368
369 UFFrame frame;369 for (auto it = unaccepted_gestures_.begin();
370 UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,370 it != unaccepted_gestures_.end();
371 &frame);371 ) {
372 if (status != UFStatusSuccess) {372 const utouch::grail::SharedGesture & gesture = *it++;
373 fprintf(stderr, "Warning: failed to get frame from event\n");373 gesture->Update(event, modified_touches);
374 return;374 if (gesture->canceled())
375 }375 RejectGesture(gesture);
376376 }
377 TouchSet modified_touches;377
378 TouchSet ended_touches;378 for (unsigned int touch_id : ended_touches)
379 GetModifiedAndEndedTouches(frame, &modified_touches,379 free_touches_.erase(touch_id);
380 &ended_touches, frame_event_get_time(event));380 }
381381
382 for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) {382
383 const SharedGesture& gesture = *it++;383
384 gesture->Update(event, modified_touches);384 void RejectGesture(const utouch::grail::SharedGesture& gesture) {
385 if (gesture->ended()) {385 gesture->Cancel();
386 for (unsigned int touch_id : gesture->touches())386 handle_->RemoveGestureFromEventQueue(gesture->id());
387 free_touches_.insert(touch_id);387 unaccepted_gestures_.erase(gesture);
388 accepted_gestures_.erase(gesture);388 }
389 }389
390 }390 Recognizer * parent_;
391391
392 for (auto it = unaccepted_gestures_.begin();392 utouch::grail::UGHandle * const handle_;
393 it != unaccepted_gestures_.end();393 const UFDevice device_;
394 ) {394 const Window window_;
395 const SharedGesture& gesture = *it++;395 float device_x_res_; /* Units of pixel/mm */
396 gesture->Update(event, modified_touches);396 float device_y_res_;
397 if (gesture->canceled())397 bool device_direct_;
398 RejectGesture(gesture);398 std::set<utouch::grail::UGSubscription*> subscriptions_[5];
399 }399 std::set<utouch::grail::SharedGesture> unaccepted_gestures_;
400400 std::set<utouch::grail::SharedGesture> accepted_gestures_;
401 for (unsigned int touch_id : ended_touches)401 std::map<unsigned int, uint64_t> start_times_;
402 free_touches_.erase(touch_id);402 TouchSet unaccepted_touches_;
403}403 TouchSet accepted_touches_;
404404 TouchSet free_touches_;
405void Recognizer::UpdateTime(uint64_t time) {405
406 for (auto it = unaccepted_gestures_.begin();406 };
407 it != unaccepted_gestures_.end();407
408 ) {408 Recognizer::Recognizer( utouch::grail::UGHandle * handle, const UFDevice device, Window window)
409 const SharedGesture& gesture = *it++;409 : d_( new Private( this, handle, device, window ) ) {
410 uint64_t timeout = gesture->Timeout();410 }
411 if (timeout && time - gesture->start_time() > timeout)411
412 RejectGesture(gesture);412 void Recognizer::ActivateSubscription( utouch::grail::UGSubscription * subscription) {
413 }413 d_->subscriptions_[subscription->touches_start() - 1].insert(subscription);
414414 }
415 for (auto it = unaccepted_touches_.begin(); it415
416 != unaccepted_touches_.end();416 void Recognizer::DeactivateSubscription( utouch::grail::UGSubscription * subscription) {
417 ) {417 d_->subscriptions_[subscription->touches_start() - 1].erase(subscription);
418 unsigned int touch_id = *it++;418
419 if (time - start_times_[touch_id] < kCompositionTime)419 for (auto it = d_->unaccepted_gestures_.begin();
420 continue;420 it != d_->unaccepted_gestures_.end();
421421 ) {
422 for (const SharedGesture& gesture : unaccepted_gestures_)422 const utouch::grail::SharedGesture & gesture = *it++;
423 if (gesture->touches().find(touch_id) != gesture->touches().end())423 if (gesture->subscription() == subscription)
424 goto next_touch;424 gesture->Cancel();
425425 d_->unaccepted_gestures_.erase(gesture);
426 frame_x11_reject_touch(device_, window_, touch_id);426 }
427 unaccepted_touches_.erase(touch_id);427
428 free_touches_.erase(touch_id);428 for (auto it = d_->accepted_gestures_.begin(); it != d_->accepted_gestures_.end(); ) {
429429 const utouch::grail::SharedGesture& gesture = *it++;
430next_touch: ;430 if (gesture->subscription() == subscription)
431 }431 gesture->Cancel();
432}432 d_->accepted_gestures_.erase(gesture);
433433 }
434uint64_t Recognizer::NextTimeout() {434 }
435 uint64_t min_timeout = std::numeric_limits<uint64_t>::max();435
436 for (unsigned int touch_id : unaccepted_touches_)436 void Recognizer::ProcessFrameEvent(const UFEvent event) {
437 if (kCompositionTime + start_times_[touch_id] < min_timeout)437 UpdateTime(frame_event_get_time(event));
438 min_timeout = start_times_[touch_id] + kCompositionTime;438 d_->MatchSubscriptionsForEvent(event);
439439 d_->ProcessEvent(event);
440 for (const SharedGesture& gesture : unaccepted_gestures_) {440 }
441 uint64_t timeout = gesture->Timeout();441
442 if (timeout && gesture->start_time() + timeout < min_timeout)442 void Recognizer::UpdateTime(uint64_t time) {
443 min_timeout = gesture->start_time() + timeout;443 for (auto it = d_->unaccepted_gestures_.begin();
444 }444 it != d_->unaccepted_gestures_.end();
445 445 ) {
446 return min_timeout;446 const utouch::grail::SharedGesture & gesture = *it++;
447}447 uint64_t timeout = gesture->Timeout();
448448 if (timeout && time - gesture->start_time() > timeout)
449UGStatus Recognizer::AcceptGesture(unsigned int id) {449 d_->RejectGesture(gesture);
450 SharedGesture gesture;450 }
451 for (const SharedGesture& test_gesture : unaccepted_gestures_) {451
452 if (test_gesture->id() == id) {452 for (auto it = d_->unaccepted_touches_.begin(); it
453 gesture = test_gesture;453 != d_->unaccepted_touches_.end();
454 break;454 ) {
455 }455 unsigned int touch_id = *it++;
456 }456 if (time - d_->start_times_[touch_id] < kCompositionTime)
457457 continue;
458 if (!gesture)458
459 return UGStatusErrorInvalidGesture;459 for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_)
460460 if (gesture->touches().find(touch_id) != gesture->touches().end())
461 for (unsigned int touch_id : gesture->touches()) {461 goto next_touch;
462 if (accepted_touches_.find(touch_id) == accepted_touches_.end()) {462
463 frame_x11_accept_touch(device_, window_, touch_id);463 frame_x11_reject_touch(d_->device_, d_->window_, touch_id);
464 accepted_touches_.insert(touch_id);464 d_->unaccepted_touches_.erase(touch_id);
465 unaccepted_touches_.erase(touch_id);465 d_->free_touches_.erase(touch_id);
466 } else {466
467 for (auto it = accepted_gestures_.begin();467 next_touch: ;
468 it != accepted_gestures_.end();468 }
469 ) {469 }
470 const SharedGesture& other_gesture = *it++;470
471 const TouchSet& other_touches = other_gesture->touches();471 uint64_t Recognizer::NextTimeout() {
472 if (other_touches.find(touch_id) != other_touches.end()) {472 uint64_t min_timeout = std::numeric_limits<uint64_t>::max();
473 gesture->Cancel();473 for (unsigned int touch_id : d_->unaccepted_touches_)
474 handle_->RemoveGestureFromEventQueue(other_gesture->id());474 if (kCompositionTime + d_->start_times_[touch_id] < min_timeout)
475 accepted_gestures_.erase(other_gesture);475 min_timeout = d_->start_times_[touch_id] + kCompositionTime;
476 }476
477 }477 for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_) {
478 }478 uint64_t timeout = gesture->Timeout();
479479 if (timeout && gesture->start_time() + timeout < min_timeout)
480 free_touches_.erase(touch_id);480 min_timeout = gesture->start_time() + timeout;
481 }481 }
482482
483 for (auto it = unaccepted_gestures_.begin();483 return min_timeout;
484 it != unaccepted_gestures_.end();484 }
485 ) {485
486 const SharedGesture& other_gesture = *it++;486 UGStatus Recognizer::AcceptGesture(unsigned int id) {
487 if (other_gesture == gesture)487 utouch::grail::SharedGesture gesture;
488 continue;488 for (const utouch::grail::SharedGesture & test_gesture : d_->unaccepted_gestures_) {
489 for (unsigned int touch_id : other_gesture->touches()) {489 if (test_gesture->id() == id) {
490 if (gesture->touches().find(touch_id) != gesture->touches().end()) {490 gesture = test_gesture;
491 RejectGesture(other_gesture);491 break;
492 break;492 }
493 }493 }
494 }494
495 }495 if (!gesture)
496496 return UGStatusErrorInvalidGesture;
497 accepted_gestures_.insert(gesture);497
498 unaccepted_gestures_.erase(gesture);498 for (unsigned int touch_id : gesture->touches()) {
499499 if (d_->accepted_touches_.find(touch_id) == d_->accepted_touches_.end()) {
500 return UGStatusSuccess;500 frame_x11_accept_touch(d_->device_, d_->window_, touch_id);
501}501 d_->accepted_touches_.insert(touch_id);
502502 d_->unaccepted_touches_.erase(touch_id);
503UGStatus Recognizer::RejectGesture(unsigned int id) {503 } else {
504 for (const SharedGesture& gesture : unaccepted_gestures_) {504 for (auto it = d_->accepted_gestures_.begin();
505 if (gesture->id() == id) {505 it != d_->accepted_gestures_.end();
506 RejectGesture(gesture);506 ) {
507 return UGStatusSuccess;507 const utouch::grail::SharedGesture & other_gesture = *it++;
508 }508 const TouchSet& other_touches = other_gesture->touches();
509 }509 if (other_touches.find(touch_id) != other_touches.end()) {
510510 gesture->Cancel();
511 return UGStatusErrorInvalidGesture;511 d_->handle_->RemoveGestureFromEventQueue(other_gesture->id());
512}512 d_->accepted_gestures_.erase(other_gesture);
513513 }
514void Recognizer::RejectGesture(const SharedGesture& gesture) {514 }
515 gesture->Cancel();515 }
516 handle_->RemoveGestureFromEventQueue(gesture->id());516
517 unaccepted_gestures_.erase(gesture);517 d_->free_touches_.erase(touch_id);
518}518 }
519519
520Recognizer::~Recognizer() {520 for (auto it = d_->unaccepted_gestures_.begin();
521 for (const SharedGesture& gesture : unaccepted_gestures_)521 it != d_->unaccepted_gestures_.end();
522 gesture->Cancel();522 ) {
523523 const utouch::grail::SharedGesture & other_gesture = *it++;
524 for (const SharedGesture& gesture : accepted_gestures_)524 if (other_gesture == gesture)
525 gesture->Cancel();525 continue;
526 for (unsigned int touch_id : other_gesture->touches()) {
527 if (gesture->touches().find(touch_id) != gesture->touches().end()) {
528 d_->RejectGesture(other_gesture);
529 break;
530 }
531 }
532 }
533
534 d_->accepted_gestures_.insert(gesture);
535 d_->unaccepted_gestures_.erase(gesture);
536
537 return UGStatusSuccess;
538 }
539
540 UGStatus Recognizer::RejectGesture(unsigned int id) {
541 for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_) {
542 if (gesture->id() == id) {
543 d_->RejectGesture(gesture);
544 return UGStatusSuccess;
545 }
546 }
547
548 return UGStatusErrorInvalidGesture;
549 }
550
551 utouch::grail::UGHandle * Recognizer::handle() const {
552 return d_->handle_;
553 }
554
555 float Recognizer::device_x_res() const {
556 return d_->device_x_res_;
557 }
558
559 float Recognizer::device_y_res() const {
560 return d_->device_y_res_;
561 }
562
563 bool Recognizer::device_direct() const {
564 return d_->device_direct_;
565 }
566
567 Recognizer::~Recognizer() {
568 for (const utouch::grail::SharedGesture& gesture : d_->unaccepted_gestures_)
569 gesture->Cancel();
570
571 for (const utouch::grail::SharedGesture& gesture : d_->accepted_gestures_)
572 gesture->Cancel();
573 }
574 }
526}575}
527576
=== modified file 'src/v3/recognizer.h'
--- src/v3/recognizer.h 2011-10-19 22:07:30 +0000
+++ src/v3/recognizer.h 2011-11-01 21:20:40 +0000
@@ -32,57 +32,44 @@
32#include "utouch/grail.h"32#include "utouch/grail.h"
33#include "v3/subscription.h"33#include "v3/subscription.h"
3434
35class Gesture;35namespace utouch {
36class UGHandle_;36 namespace grail {
3737
38typedef std::set<unsigned int> TouchSet;38 class UGHandle;
39typedef std::shared_ptr<Gesture> SharedGesture;39 class UGSubscription;
4040
41class Recognizer {41 class Gesture;
42 public:42 typedef std::shared_ptr<Gesture> SharedGesture;
43 Recognizer(UGHandle_* handle, const UFDevice device, Window window);43
44 ~Recognizer();44 typedef std::set<unsigned int> TouchSet;
4545
46 void ActivateSubscription(UGSubscription_* subscription);46 class Recognizer {
47 void DeactivateSubscription(UGSubscription_* subscription);47 public:
48 void ProcessFrameEvent(const UFEvent event);48 Recognizer( utouch::grail::UGHandle * handle, const UFDevice device, Window window);
49 void UpdateTime(uint64_t time);49 ~Recognizer();
50 uint64_t NextTimeout();50
51 UGStatus AcceptGesture(unsigned int id);51 void ActivateSubscription( utouch::grail::UGSubscription * subscription );
52 UGStatus RejectGesture(unsigned int id);52 void DeactivateSubscription( utouch::grail::UGSubscription* subscription);
5353 void ProcessFrameEvent(const UFEvent event);
54 UGHandle_* handle() const { return handle_; }54 void UpdateTime(uint64_t time);
55 float device_x_res() const { return device_x_res_; }55 uint64_t NextTimeout();
56 float device_y_res() const { return device_y_res_; }56 UGStatus AcceptGesture(unsigned int id);
57 bool device_direct() const { return device_direct_; }57 UGStatus RejectGesture(unsigned int id);
5858
59 Recognizer(const Recognizer&) = delete;59 utouch::grail::UGHandle * handle() const;
60 void operator=(const Recognizer&) = delete;60 float device_x_res() const;
6161 float device_y_res() const;
62 private:62 bool device_direct() const;
63 UGHandle_* const handle_;63
64 const UFDevice device_;64 Recognizer(const Recognizer&) = delete;
65 const Window window_;65 void operator=(const Recognizer&) = delete;
66 float device_x_res_; /* Units of pixel/mm */66
67 float device_y_res_;67 protected:
68 bool device_direct_;68
69 std::set<UGSubscription_*> subscriptions_[5];69 struct Private;
70 std::set<SharedGesture> unaccepted_gestures_;70 std::shared_ptr< Private > d_;
71 std::set<SharedGesture> accepted_gestures_;71
72 std::map<unsigned int, uint64_t> start_times_;72 };
73 TouchSet unaccepted_touches_;73 }
74 TouchSet accepted_touches_;74}
75 TouchSet free_touches_;
76
77 void MatchSubscriptionsForEvent(const UFEvent event);
78 void MatchSubscriptionsForTouch(unsigned int touch_id);
79 void MatchOneTouchGestures(unsigned int touch_id);
80 void MatchTwoTouchGestures(unsigned int touch_id);
81 void MatchThreeTouchGestures(unsigned int touch_id);
82 void MatchFourTouchGestures(unsigned int touch_id);
83 void MatchFiveTouchGestures(unsigned int touch_id);
84 void ProcessEvent(const UFEvent& event);
85 void RejectGesture(const SharedGesture& gesture);
86};
87
88#endif // UTOUCH_GRAIL_RECOGNIZER_H_75#endif // UTOUCH_GRAIL_RECOGNIZER_H_
8976
=== modified file 'src/v3/slice.cpp'
--- src/v3/slice.cpp 2011-10-21 00:06:58 +0000
+++ src/v3/slice.cpp 2011-11-01 21:20:40 +0000
@@ -21,10 +21,10 @@
2121
22#include "v3/slice.h"22#include "v3/slice.h"
2323
24#include <assert.h>24#include <cassert>
25#include <math.h>25#include <cmath>
26#include <stdio.h>26#include <cstdio>
27#include <string.h>27#include <cstring>
2828
29#include <utouch/frame.h>29#include <utouch/frame.h>
3030
@@ -32,550 +32,687 @@
32#include "v3/recognizer.h"32#include "v3/recognizer.h"
33#include "v3/subscription.h"33#include "v3/subscription.h"
3434
35namespace {35namespace utouch {
3636 namespace grail {
37const UGTransform kIdentityTransform = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };37
3838 const UGTransform kIdentityTransform = {
39} // namespace39 { 1, 0, 0 },
4040 { 0, 1, 0 },
41UGSlice_::UGSlice_(const SharedGesture& gesture, UFEvent event,41 { 0, 0, 1 }
42 const TouchSet& touches, UGGestureTypeMask recognized)42 };
43 : gesture_(gesture),43
44 event_(event),44 struct UGSlice::Private {
45 frame_(NULL),45
46 touches_(touches),46 Private( const SharedUGSlice & prev,
47 time_(frame_event_get_time(event)),47 UFEvent event,
48 state_(UGGestureStateBegin),48 const TouchSet & touches )
49 original_center_x_(0),49 : gesture_(prev->d_->gesture_),
50 original_center_y_(0),50 event_(event ? : NULL),
51 original_radius_(0),51 frame_(NULL),
52 original_angle_(0),52 touches_(touches),
53 radius_(0),53 time_(frame_event_get_time(event)),
54 angle_(0),54 state_(UGGestureStateUpdate),
55 center_of_rotation_x_(0),55 original_center_x_(prev->d_->original_center_x_),
56 center_of_rotation_y_(0),56 original_center_y_(prev->d_->original_center_y_),
57 recognized_(recognized),57 original_radius_(prev->d_->original_radius_),
58 touch_count_changed_(false) {58 original_angle_(prev->d_->original_angle_),
59 frame_event_ref(event);59 radius_(prev->d_->radius_),
6060 angle_(prev->d_->angle_),
61 memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform));61 center_of_rotation_x_(0),
62 memcpy(cumulative_transform_, kIdentityTransform, sizeof(kIdentityTransform));62 center_of_rotation_y_(0),
63}63 recognized_(prev->d_->recognized_),
6464 touch_count_changed_(touches_.size() != prev->d_->touches_.size()) {
65UGSlice_* UGSlice_::NewUGSlice_(const SharedGesture& gesture, UFEvent event,65
66 const TouchSet& touches,66 ::memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform));
67 UGGestureTypeMask recognized) {67
68 UGSlice_* slice = new UGSlice_(gesture, event, touches, recognized);68 if( touch_count_changed_ ) {
6969 ::memcpy( cumulative_transform_,
70 UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,70 kIdentityTransform,
71 &slice->frame_);71 sizeof( kIdentityTransform )
72 if (status != UFStatusSuccess) {72 );
73 fprintf(stderr, "Warning: failed to get frame from event\n");73 original_radius_ = 0;
74 delete slice;74 original_angle_ = 0;
75 return NULL;75 } else {
76 }76 memcpy( cumulative_transform_,
7777 prev->d_->cumulative_transform_,
78 slice->GetValues(touches, &slice->original_center_x_,78 sizeof(prev->d_->cumulative_transform_)
79 &slice->original_center_y_, &slice->original_radius_,79 );
80 &slice->original_angle_, true);80 }
81 slice->radius_ = slice->original_radius_;81
82 slice->angle_ = slice->original_angle_;82 if (event_)
8383 frame_event_ref(event_);
84 return slice;84 }
85}85
8686 Private( const SharedGesture & gesture,
87UGSlice_::UGSlice_(const SharedUGSlice_& prev, UFEvent event,87 UFEvent event,
88 const TouchSet& touches)88 const TouchSet & touches,
89 : gesture_(prev->gesture_),89 UGGestureTypeMask recognized )
90 event_(event ? : NULL),90 : gesture_(gesture),
91 frame_(NULL),91 event_(event),
92 touches_(touches),92 frame_(NULL),
93 time_(frame_event_get_time(event)),93 touches_(touches),
94 state_(UGGestureStateUpdate),94 time_(frame_event_get_time(event)),
95 original_center_x_(prev->original_center_x_),95 state_(UGGestureStateBegin),
96 original_center_y_(prev->original_center_y_),96 original_center_x_(0),
97 original_radius_(prev->original_radius_),97 original_center_y_(0),
98 original_angle_(prev->original_angle_),98 original_radius_(0),
99 radius_(prev->radius_),99 original_angle_(0),
100 angle_(prev->angle_),100 radius_(0),
101 center_of_rotation_x_(0),101 angle_(0),
102 center_of_rotation_y_(0),102 center_of_rotation_x_(0),
103 recognized_(prev->recognized_),103 center_of_rotation_y_(0),
104 touch_count_changed_(touches_.size() != prev->touches_.size()) {104 recognized_(recognized),
105 memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform));105 touch_count_changed_(false) {
106106
107 if (touch_count_changed_) {107 frame_event_ref(event);
108 memcpy(cumulative_transform_, kIdentityTransform,108
109 sizeof(kIdentityTransform));109 memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform));
110 original_radius_ = 0;110 memcpy(cumulative_transform_, kIdentityTransform, sizeof(kIdentityTransform));
111 original_angle_ = 0;111 }
112 } else {112
113 memcpy(cumulative_transform_, prev->cumulative_transform_,113 ~Private() {
114 sizeof(prev->cumulative_transform_));114 frame_event_unref(event_);
115 }115 }
116116
117 if (event_)117 const std::weak_ptr<Gesture> gesture_;
118 frame_event_ref(event_);118 SharedGesture gesture_ref_;
119}119 const UFEvent event_;
120120 UFFrame frame_;
121UGSlice_* UGSlice_::NewUGSlice_(const SharedUGSlice_& prev, UFEvent event,121 TouchSet touches_;
122 const TouchSet& touches) {122 uint64_t time_;
123 UGSlice_* slice = new UGSlice_(prev, event, touches);123 UGGestureState state_;
124124 float original_center_x_;
125 UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,125 float original_center_y_;
126 &slice->frame_);126 float original_radius_;
127 if (status != UFStatusSuccess) {127 float original_angle_;
128 fprintf(stderr, "Warning: failed to get frame from event\n");128 float radius_;
129 delete slice;129 float angle_;
130 return NULL;130 float transform_[3][3];
131 }131 float cumulative_transform_[3][3];
132132 float center_of_rotation_x_;
133 if (slice->touch_count_changed_) {133 float center_of_rotation_y_;
134 slice->GetValues(touches, &slice->original_center_x_,134 UGGestureTypeMask recognized_;
135 &slice->original_center_y_, &slice->original_radius_,135 bool touch_count_changed_;
136 &slice->original_angle_, true);136
137 slice->radius_ = slice->original_radius_;137 void GetValues( const TouchSet & touches,
138 slice->angle_ = slice->original_angle_;138 float * x,
139 } else {139 float * y,
140 slice->SetTransforms();140 float * radius,
141 slice->SetCenterOfRotation();141 float* angle,
142 slice->CheckGestureEnd();142 bool init
143 }143 ) {
144144 assert( x == NULL );
145 return slice;145 assert( y == NULL );
146}146 assert( radius == NULL );
147147 assert( angle == NULL );
148void UGSlice_::GetValues(const TouchSet& touches, float* x, float* y,148
149 float* radius, float* angle, bool init) {149 *x = 0;
150 *x = 0;150 *y = 0;
151 *y = 0;151
152152 for (unsigned int touch_id : touches) {
153 for (unsigned int touch_id : touches) {153 UFTouch touch;
154 UFTouch touch;154 UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
155 UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);155 if (status != UFStatusSuccess) {
156 if (status != UFStatusSuccess) {156 fprintf(stderr, "Warning: failed to get touch from frame\n");
157 fprintf(stderr, "Warning: failed to get touch from frame\n");157 continue;
158 continue;158 }
159 }159
160 160 if (gesture_.lock()->recognizer().device_direct()) {
161 if (gesture_.lock()->recognizer().device_direct()) {161 *x += frame_touch_get_window_x(touch);
162 *x += frame_touch_get_window_x(touch);162 *y += frame_touch_get_window_y(touch);
163 *y += frame_touch_get_window_y(touch);163 } else {
164 } else {164 *x += frame_touch_get_device_x(touch);
165 *x += frame_touch_get_device_x(touch);165 *y += frame_touch_get_device_y(touch);
166 *y += frame_touch_get_device_y(touch);166 }
167 }167 }
168 }168
169169 *x /= touches.size();
170 *x /= touches.size();170 *y /= touches.size();
171 *y /= touches.size();171
172172 if (touches.size() == 1)
173 if (touches.size() == 1)173 return;
174 return;174
175175 *radius = 0;
176 *radius = 0;176 *angle = 0;
177 *angle = 0;177 int num_angles = 0;
178 int num_angles = 0;178 for (unsigned int touch_id : touches) {
179 for (unsigned int touch_id : touches) {179 UFTouch touch;
180 UFTouch touch;180 float cur_x;
181 float cur_x;181 float cur_y;
182 float cur_y;182
183183 UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
184 UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);184 if (status != UFStatusSuccess) {
185 if (status != UFStatusSuccess) {185 fprintf(stderr, "Warning: failed to get touch from frame\n");
186 fprintf(stderr, "Warning: failed to get touch from frame\n");186 continue;
187 continue;187 }
188 }188
189189 if (gesture_.lock()->recognizer().device_direct()) {
190 if (gesture_.lock()->recognizer().device_direct()) {190 cur_x = frame_touch_get_window_x(touch);
191 cur_x = frame_touch_get_window_x(touch);191 cur_y = frame_touch_get_window_y(touch);
192 cur_y = frame_touch_get_window_y(touch);192 } else {
193 } else {193 cur_x = frame_touch_get_device_x(touch);
194 cur_x = frame_touch_get_device_x(touch);194 cur_y = frame_touch_get_device_y(touch);
195 cur_y = frame_touch_get_device_y(touch);195 }
196 }196
197197 *radius += sqrtf((cur_x - *x) * (cur_x - *x) + (cur_y - *y) * (cur_y - *y));
198 *radius += sqrtf((cur_x - *x) * (cur_x - *x) + (cur_y - *y) * (cur_y - *y));198
199199 float new_angle = atan2f(cur_y - *y, cur_x - *x);
200 float new_angle = atan2f(cur_y - *y, cur_x - *x);200
201201 if (init) {
202 if (init) {202 *angle += new_angle;
203 *angle += new_angle;203 num_angles++;
204 num_angles++;204 } else if (frame_touch_get_state(touch) != UFTouchStateBegin) {
205 } else if (frame_touch_get_state(touch) != UFTouchStateBegin) {205 float prev_angle = gesture_.lock()->AngleForTouch(touch_id);
206 float prev_angle = gesture_.lock()->AngleForTouch(touch_id);206
207207 if (new_angle - prev_angle < -M_PI)
208 if (new_angle - prev_angle < -M_PI)208 new_angle += 2 * M_PI;
209 new_angle += 2 * M_PI;209 else if (new_angle - prev_angle > M_PI)
210 else if (new_angle - prev_angle > M_PI)210 new_angle -= 2 * M_PI;
211 new_angle -= 2 * M_PI;211
212212 *angle += new_angle - prev_angle;
213 *angle += new_angle - prev_angle;213 num_angles++;
214 num_angles++;214 }
215 }215
216216 gesture_.lock()->SetAngleForTouch(touch_id, new_angle);
217 gesture_.lock()->SetAngleForTouch(touch_id, new_angle);217 }
218 }218
219219 *radius /= touches.size();
220 *radius /= touches.size();220 *angle /= num_angles;
221 *angle /= num_angles;221 if (!init)
222 if (!init)222 *angle += angle_;
223 *angle += angle_;223 }
224}224
225225 /**
226void UGSlice_::SetTransforms() {226 * Determine the center of rotation point.
227 float center_x;227 *
228 float center_y;228 * For any given point q that is transformed by a 2D affine transformation
229 float new_radius = radius_;229 * matrix T about anchor point P the new point q' may be determined by the
230 float new_angle = angle_;230 * following equation:
231 GetValues(touches_, &center_x, &center_y, &new_radius, &new_angle, false);231 *
232232 * q' = T * (q - P) + P
233 if (!touch_count_changed_) {233 *
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
235235 * other. We will label the original T and P as T0 and P0, and the new values
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
237 transform_[0][1] = -sinf(new_angle - angle_) * scale;237 * equation:
238 transform_[0][2] =238 *
239 center_x - cumulative_transform_[0][2] - original_center_x_;239 * q' = T0 * (q - P0) + P0 = T1 * (q - P1) + P1
240 transform_[1][0] = -transform_[0][1];240 *
241 transform_[1][1] = transform_[0][0];241 * In the calculations below, we use variables for the scalar values
242 transform_[1][2] =242 * that make up T0, P0, T1, and P1:
243 center_y - cumulative_transform_[1][2] - original_center_y_;243 *
244244 * T0: [ a -b c ] P0: [ x0 ] T1: [ a -b 0 ] P1: [ x1 ]
245 scale = original_radius_ ? new_radius / original_radius_ : 1;245 * [ b a d ] [ y0 ] [ b a 0 ] [ y1 ]
246246 * [ 0 0 1 ] [ 0 ] [ 0 0 1 ] [ 0 ]
247 cumulative_transform_[0][0] = cosf(new_angle - original_angle_) * scale;247 *
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
249 cumulative_transform_[0][2] = center_x - original_center_x_;249 * b are equivalent between the transformation matrices.
250 cumulative_transform_[1][0] = -cumulative_transform_[0][1];250 *
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
252 cumulative_transform_[1][2] = center_y - original_center_y_;252 * x1 and y1 in P1.
253 } else {253 */
254 original_radius_ += new_radius - radius_;254 void SetCenterOfRotation() {
255 original_angle_ += new_angle - angle_;255 float a = transform_[0][0];
256 original_center_x_ +=256 float b = transform_[1][0];
257 center_x - (original_center_x_ + cumulative_transform_[0][2]);257 float c = transform_[0][2];
258 original_center_y_ +=258 float d = transform_[0][2];
259 center_y - (original_center_y_ + cumulative_transform_[1][2]);259 float x0 = original_center_x_ + cumulative_transform_[0][2];
260 }260 float y0 = original_center_y_ + cumulative_transform_[1][2];
261261 float x1;
262 radius_ = new_radius;262 float y1;
263 angle_ = new_angle;263
264}264 float div = a*a - 2*a + b*b + 1;
265265
266/**266 // TODO: Replace magic number here :-)
267 * Determine the center of rotation point.267 if( ::fabsf( div ) < 1e-5 )
268 *268 return;
269 * For any given point q that is transformed by a 2D affine transformation269
270 * matrix T about anchor point P the new point q' may be determined by the270 x1 = (a*a*x0 - a*(2*x0+c) + b*b*x0 - b*d + c + x0) / div;
271 * following equation:271 y1 = (a*a*y0 - a*(2*y0+d) + b*b*y0 + b*c + d + y0) / div;
272 *272
273 * q' = T * (q - P) + P273 center_of_rotation_x_ = x1;
274 *274 center_of_rotation_y_ = y1;
275 * T and P are dependent, so we can modify one and find a new value for the275 }
276 * other. We will label the original T and P as T0 and P0, and the new values276
277 * will be labeled T1 and P1. We can find new values by solving the following277 void CheckGestureEnd() {
278 * equation:278 std::size_t num_active_touches = 0;
279 *279
280 * q' = T0 * (q - P0) + P0 = T1 * (q - P1) + P1280 for (unsigned int touch_id : touches_) {
281 *281 UFTouch touch;
282 * In the calculations below, we use variables for the scalar values282 UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
283 * that make up T0, P0, T1, and P1:283 if (status != UFStatusSuccess) {
284 *284 fprintf(stderr, "Warning: failed to get touch from frame by id\n");
285 * T0: [ a -b c ] P0: [ x0 ] T1: [ a -b 0 ] P1: [ x1 ]285 continue;
286 * [ b a d ] [ y0 ] [ b a 0 ] [ y1 ]286 }
287 * [ 0 0 1 ] [ 0 ] [ 0 0 1 ] [ 0 ]287
288 *288 if (frame_touch_get_state(touch) == UFTouchStateEnd) {
289 * Note that rotation and scaling are independent of the anchor point, so a and289 continue;
290 * b are equivalent between the transformation matrices.290 } else {
291 *291 int pending_end;
292 * Since we know all the values of T0, P0, and T1, we can calculate the values292 status = frame_touch_get_property(touch, UFTouchPropertyPendingEnd,
293 * x1 and y1 in P1.293 &pending_end);
294 */294 if (status != UFStatusSuccess) {
295void UGSlice_::SetCenterOfRotation() {295 fprintf(stderr, "Warning: failed to get touch pending end property\n");
296 float a = transform_[0][0];296 continue;
297 float b = transform_[1][0];297 }
298 float c = transform_[0][2];298
299 float d = transform_[0][2];299 if (pending_end)
300 float x0 = original_center_x_ + cumulative_transform_[0][2];300 continue;
301 float y0 = original_center_y_ + cumulative_transform_[1][2];301 }
302 float x1;302
303 float y1;303 num_active_touches++;
304304 }
305 float div = a*a - 2*a + b*b + 1;305
306306 const UGSubscription * subscription = gesture_.lock()->subscription();
307 if (fabsf(div) < 1e-5)307 unsigned int touches_start = subscription->touches_start();
308 return;308 unsigned int touches_min = subscription->touches_min();
309309 if ((!touches_min && num_active_touches < touches_start) ||
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))
311 y1 = (a*a*y0 - a*(2*y0+d) + b*b*y0 + b*c + d + y0) / div;311 state_ = UGGestureStateEnd;
312312 }
313 center_of_rotation_x_ = x1;313
314 center_of_rotation_y_ = y1;314 void SetTransforms() {
315}315 float center_x;
316316 float center_y;
317void UGSlice_::CheckGestureEnd() {317 float new_radius = radius_;
318 unsigned int num_active_touches = 0;318 float new_angle = angle_;
319 for (unsigned int touch_id : touches_) {319 GetValues( touches_, &center_x, &center_y, &new_radius, &new_angle, false);
320 UFTouch touch;320
321 UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);321 if (touch_count_changed_) {
322 if (status != UFStatusSuccess) {322 float scale = radius_ > 0 ? new_radius / radius_ : 1;
323 fprintf(stderr, "Warning: failed to get touch from frame by id\n");323
324 continue;324 transform_[0][0] = cosf(new_angle - angle_) * scale;
325 }325 transform_[0][1] = -sinf(new_angle - angle_) * scale;
326326 transform_[0][2] =
327 if (frame_touch_get_state(touch) == UFTouchStateEnd) {327 center_x - cumulative_transform_[0][2] - original_center_x_;
328 continue;328 transform_[1][0] = -transform_[0][1];
329 } else {329 transform_[1][1] = transform_[0][0];
330 int pending_end;330 transform_[1][2] =
331 status = frame_touch_get_property(touch, UFTouchPropertyPendingEnd,331 center_y - cumulative_transform_[1][2] - original_center_y_;
332 &pending_end);332
333 if (status != UFStatusSuccess) {333 scale = original_radius_ > 0 ? new_radius / original_radius_ : 1;
334 fprintf(stderr, "Warning: failed to get touch pending end property\n");334
335 continue;335 cumulative_transform_[0][0] = ::cosf( new_angle - original_angle_ ) * scale;
336 }336 cumulative_transform_[0][1] = -::sinf( new_angle - original_angle_ ) * scale;
337337 cumulative_transform_[0][2] = center_x - original_center_x_;
338 if (pending_end)338 cumulative_transform_[1][0] = -cumulative_transform_[0][1];
339 continue;339 cumulative_transform_[1][1] = cumulative_transform_[0][0];
340 }340 cumulative_transform_[1][2] = center_y - original_center_y_;
341341 } else {
342 num_active_touches++;342 original_radius_ += new_radius - radius_;
343 }343 original_angle_ += new_angle - angle_;
344344 original_center_x_ +=
345 const UGSubscription_* subscription = gesture_.lock()->subscription();345 center_x - (original_center_x_ + cumulative_transform_[0][2]);
346 unsigned int touches_start = subscription->touches_start();346 original_center_y_ +=
347 unsigned int touches_min = subscription->touches_min();347 center_y - (original_center_y_ + cumulative_transform_[1][2]);
348 if ((!touches_min && num_active_touches < touches_start) ||348 }
349 (touches_min && num_active_touches < touches_min))349
350 state_ = UGGestureStateEnd;350 radius_ = new_radius;
351}351 angle_ = new_angle;
352352 }
353uint64_t UGSlice_::CumulativeTime() const {353
354 return time_ - gesture_.lock()->start_time();354 uint64_t CumulativeTime() const {
355}355 return( time_ - gesture_.lock()->start_time() );
356356 }
357float UGSlice_::CumulativeDrag2() const {357
358 float res_x = gesture_.lock()->recognizer().device_x_res();358 float CumulativeDrag2() const {
359 float res_y = gesture_.lock()->recognizer().device_y_res();359 float res_x = gesture_.lock()->recognizer().device_x_res();
360360 float res_y = gesture_.lock()->recognizer().device_y_res();
361 return fabsf(cumulative_transform_[0][2] / res_x *361
362 cumulative_transform_[0][2] / res_x +362 return fabsf(cumulative_transform_[0][2] / res_x *
363 cumulative_transform_[1][2] / res_y * 363 cumulative_transform_[0][2] / res_x +
364 cumulative_transform_[1][2] / res_y);364 cumulative_transform_[1][2] / res_y *
365}365 cumulative_transform_[1][2] / res_y);
366366 }
367float UGSlice_::CumulativePinch() const {367
368 float pinch = original_radius_ ? radius_ / original_radius_ : 1;368 float CumulativePinch() const {
369369 float pinch = original_radius_ > 0 ? radius_ / original_radius_ : 1;
370 return (pinch >= 1 ? pinch : 1 / pinch);370
371}371 return( pinch < 1 ? 1 / pinch : pinch );
372372 }
373UGGestureTypeMask UGSlice_::CheckRecognition(373 };
374 const UGSubscription_& subscription) {374
375 if ((subscription.mask() & UGGestureTypeDrag) &&375
376 (!subscription.drag().timeout() ||376
377 CumulativeTime() < subscription.drag().timeout()) &&377 UGSlice::UGSlice( const SharedGesture & gesture,
378 CumulativeDrag2() > subscription.drag().threshold())378 UFEvent event,
379 recognized_ |= UGGestureTypeDrag;379 const TouchSet & touches,
380380 UGGestureTypeMask recognized)
381 if ((subscription.mask() & UGGestureTypePinch) &&381 : d_( new Private( gesture, event, touches, recognized ) ) {
382 (!subscription.pinch().timeout() ||382
383 CumulativeTime() < subscription.pinch().timeout()) &&383 }
384 CumulativePinch() > subscription.pinch().threshold())384
385 recognized_ |= UGGestureTypePinch;385 UGSlice::UGSlice( const SharedUGSlice & prev,
386386 UFEvent event,
387 if ((subscription.mask() & UGGestureTypeRotate) &&387 const TouchSet& touches )
388 (!subscription.rotate().timeout() ||388 : d_( new Private( prev, event, touches ) ) {
389 CumulativeTime() < subscription.rotate().timeout()) &&389 }
390 fabsf(angle_ - original_angle_) > subscription.rotate().threshold())390
391 recognized_ |= UGGestureTypeRotate;391 UGSlice* UGSlice::NewUGSlice( const SharedGesture & gesture,
392392 UFEvent event,
393 if ((subscription.mask() & UGGestureTypeTap) &&393 const TouchSet & touches,
394 CumulativeTime() < subscription.tap().timeout() &&394 UGGestureTypeMask recognized ) {
395 state_ == UGGestureStateEnd)395
396 recognized_ |= UGGestureTypeTap;396 UGSlice* slice = new UGSlice(gesture, event, touches, recognized);
397397
398 if (subscription.mask() & UGGestureTypeTouch)398 UFStatus status = frame_event_get_property( event,
399 recognized_ |= UGGestureTypeTouch;399 UFEventPropertyFrame,
400400 &slice->d_->frame_);
401 return recognized_;401 if (status != UFStatusSuccess) {
402}402 fprintf(stderr, "Warning: failed to get frame from event\n");
403403 delete slice;
404UGStatus UGSlice_::GetTouchId(unsigned int index, void* touch_id) const {404 return NULL;
405 auto it = touches_.begin();405 }
406 for (unsigned int i = 0; i < index; ++i, ++it)406
407 if (it == touches_.end())407 slice->d_->GetValues( touches,
408 return UGStatusErrorInvalidIndex;408 &slice->d_->original_center_x_,
409409 &slice->d_->original_center_y_,
410 *reinterpret_cast<unsigned int*>(touch_id) = *it;410 &slice->d_->original_radius_,
411 return UGStatusSuccess;411 &slice->d_->original_angle_,
412}412 true);
413413
414UGStatus UGSlice_::GetProperty(UGSliceProperty property, void* value) const {414 slice->d_->radius_ = slice->d_->original_radius_;
415 switch (property) {415 slice->d_->angle_ = slice->d_->original_angle_;
416 case UGSlicePropertyId:416
417 *reinterpret_cast<unsigned int*>(value) = gesture_.lock()->id();417 return slice;
418 return UGStatusSuccess;418 }
419419
420 case UGSlicePropertyState:420 UGSlice* UGSlice::NewUGSlice(const SharedUGSlice& prev, UFEvent event,
421 *reinterpret_cast<UGGestureState*>(value) = state_;421 const TouchSet& touches) {
422 return UGStatusSuccess;422 UGSlice* slice = new UGSlice(prev, event, touches);
423423
424 case UGSlicePropertySubscription:424 UFStatus status = frame_event_get_property( event,
425 *reinterpret_cast<UGSubscription*>(value) = gesture_.lock()->subscription();425 UFEventPropertyFrame,
426 return UGStatusSuccess;426 &slice->d_->frame_ );
427427 if (status != UFStatusSuccess) {
428 case UGSlicePropertyRecognized:428 fprintf(stderr, "Warning: failed to get frame from event\n");
429 *reinterpret_cast<UGGestureTypeMask*>(value) = recognized_;429 delete slice;
430 return UGStatusSuccess;430 return NULL;
431431 }
432 case UGSlicePropertyNumTouches:432
433 *reinterpret_cast<unsigned int*>(value) = touches_.size();433 if (slice->d_->touch_count_changed_) {
434 return UGStatusSuccess;434 slice->d_->GetValues( touches,
435435 &slice->d_->original_center_x_,
436 case UGSlicePropertyFrame:436 &slice->d_->original_center_y_,
437 *reinterpret_cast<UFFrame*>(value) = frame_;437 &slice->d_->original_radius_,
438 return UGStatusSuccess;438 &slice->d_->original_angle_,
439439 true);
440 case UGSlicePropertyOriginalCenterX:440 slice->d_->radius_ = slice->d_->original_radius_;
441 *reinterpret_cast<float*>(value) = original_center_x_;441 slice->d_->angle_ = slice->d_->original_angle_;
442 return UGStatusSuccess;442 } else {
443443 slice->d_->SetTransforms();
444 case UGSlicePropertyOriginalCenterY:444 slice->d_->SetCenterOfRotation();
445 *reinterpret_cast<float*>(value) = original_center_y_;445 slice->d_->CheckGestureEnd();
446 return UGStatusSuccess;446 }
447447
448 case UGSlicePropertyOriginalRadius:448 return slice;
449 *reinterpret_cast<float*>(value) = original_radius_;449 }
450 return UGStatusSuccess;450
451451 UGGestureTypeMask UGSlice::CheckRecognition( const UGSubscription & subscription ) {
452 case UGSlicePropertyTransform:452 if ((subscription.mask() & UGGestureTypeDrag ) &&
453 *reinterpret_cast<UGTransform**>(value) = &transform_;453 (!subscription.drag().timeout_ ||
454 return UGStatusSuccess;454 d_->CumulativeTime() < subscription.drag().timeout_) &&
455455 d_->CumulativeDrag2() > subscription.drag().threshold_)
456 case UGSlicePropertyCumulativeTransform:456 d_->recognized_ |= UGGestureTypeDrag;
457 *reinterpret_cast<UGTransform**>(value) = &cumulative_transform_;457
458 return UGStatusSuccess;458 if ((subscription.mask() & UGGestureTypePinch) &&
459459 (!subscription.pinch().timeout_ ||
460 case UGSlicePropertyCenterOfRotationX:460 d_->CumulativeTime() < subscription.pinch().timeout_) &&
461 *reinterpret_cast<float*>(value) = center_of_rotation_x_;461 d_->CumulativePinch() > subscription.pinch().threshold_)
462 return UGStatusSuccess;462 d_->recognized_ |= UGGestureTypePinch;
463463
464 case UGSlicePropertyCenterOfRotationY:464 if ((subscription.mask() & UGGestureTypeRotate) &&
465 *reinterpret_cast<float*>(value) = center_of_rotation_y_;465 (!subscription.rotate().timeout_ ||
466 return UGStatusSuccess;466 d_->CumulativeTime() < subscription.rotate().timeout_) &&
467 }467 ::fabsf( d_->angle_ - d_->original_angle_) > subscription.rotate().threshold_)
468468 d_->recognized_ |= UGGestureTypeRotate;
469 return UGStatusErrorUnknownProperty;469
470}470 if ((subscription.mask() & UGGestureTypeTap) &&
471471 d_->CumulativeTime() < subscription.tap().timeout_ &&
472UGSlice_::~UGSlice_() {472 d_->state_ == UGGestureStateEnd)
473 frame_event_unref(event_);473 d_->recognized_ |= UGGestureTypeTap;
474}474
475475 if (subscription.mask() & UGGestureTypeTouch)
476extern "C" {476 d_->recognized_ |= UGGestureTypeTouch;
477477
478UGStatus grail_slice_get_property(const UGSlice slice, UGSliceProperty property,478 return( d_->recognized_ );
479 void* value) {479 }
480 return slice->GetProperty(property, value);480
481}481 // Might be a performance penalty.
482482 UGStatus UGSlice::GetTouchId(unsigned int index, void* touch_id) const {
483unsigned int grail_slice_get_id(const UGSlice slice) {483
484 unsigned int id;484 assert( touch_id == NULL );
485 UGStatus status = slice->GetProperty(UGSlicePropertyId, &id);485
486 assert(status == UGStatusSuccess);486 auto it = d_->touches_.begin();
487 return id;487 for( unsigned int i = 0; i < index; ++i, ++it )
488}488 if( it == d_->touches_.end() )
489489 return UGStatusErrorInvalidIndex;
490UGGestureState grail_slice_get_state(const UGSlice slice) {490
491 UGGestureState state;491 *reinterpret_cast<unsigned int*>( touch_id ) = *it;
492 UGStatus status = slice->GetProperty(UGSlicePropertyState, &state);492 return( UGStatusSuccess );
493 assert(status == UGStatusSuccess);493 }
494 return state;494
495}495 UGStatus UGSlice::GetProperty(UGSliceProperty property, void* value) const {
496496 assert( value == NULL );
497UGGestureTypeMask grail_slice_get_recognized(const UGSlice slice) {497 switch( property ) {
498 UGGestureTypeMask mask;498 case UGSlicePropertyId:
499 UGStatus status = slice->GetProperty(UGSlicePropertyRecognized, &mask);499 *reinterpret_cast<unsigned int*>(value) = d_->gesture_.lock()->id();
500 assert(status == UGStatusSuccess);500 return UGStatusSuccess;
501 return mask;501
502}502 case UGSlicePropertyState:
503503 *reinterpret_cast<UGGestureState*>( value ) = d_->state_;
504UGSubscription grail_slice_get_subscription(const UGSlice slice) {504 return UGStatusSuccess;
505 UGSubscription subscription;505
506 UGStatus status = slice->GetProperty(UGSlicePropertySubscription,506 case UGSlicePropertySubscription:
507 &subscription);507 *reinterpret_cast<void**>( value ) = d_->gesture_.lock()->subscription();
508 assert(status == UGStatusSuccess);508 return UGStatusSuccess;
509 return subscription;509
510}510 case UGSlicePropertyRecognized:
511511 *reinterpret_cast<UGGestureTypeMask*>(value) = d_->recognized_;
512unsigned int grail_slice_get_num_touches(const UGSlice slice) {512 return UGStatusSuccess;
513 unsigned int num_touches;513
514 UGStatus status = slice->GetProperty(UGSlicePropertyNumTouches, &num_touches);514 case UGSlicePropertyNumTouches:
515 assert(status == UGStatusSuccess);515 *reinterpret_cast<unsigned int*>(value) = d_->touches_.size();
516 return num_touches;516 return UGStatusSuccess;
517}517
518518 case UGSlicePropertyFrame:
519UGStatus grail_slice_get_touch_id(const UGSlice slice, unsigned int index,519 *reinterpret_cast<UFFrame*>(value) = d_->frame_;
520 void *touch_id) {520 return UGStatusSuccess;
521 return slice->GetTouchId(index, touch_id);521
522}522 case UGSlicePropertyOriginalCenterX:
523523 *reinterpret_cast<float*>(value) = d_->original_center_x_;
524float grail_slice_get_original_center_x(const UGSlice slice) {524 return UGStatusSuccess;
525 float x;525
526 UGStatus status = slice->GetProperty(UGSlicePropertyOriginalCenterX, &x);526 case UGSlicePropertyOriginalCenterY:
527 assert(status == UGStatusSuccess);527 *reinterpret_cast<float*>(value) = d_->original_center_y_;
528 return x;528 return UGStatusSuccess;
529}529
530530 case UGSlicePropertyOriginalRadius:
531float grail_slice_get_original_center_y(const UGSlice slice) {531 *reinterpret_cast<float*>(value) = d_->original_radius_;
532 float y;532 return UGStatusSuccess;
533 UGStatus status = slice->GetProperty(UGSlicePropertyOriginalCenterY, &y);533
534 assert(status == UGStatusSuccess);534 case UGSlicePropertyTransform:
535 return y;535 *reinterpret_cast<UGTransform**>(value) = &d_->transform_;
536}536 return UGStatusSuccess;
537537
538float grail_slice_get_original_radius(const UGSlice slice) {538 case UGSlicePropertyCumulativeTransform:
539 float radius;539 *reinterpret_cast<UGTransform**>(value) = &d_->cumulative_transform_;
540 UGStatus status = slice->GetProperty(UGSlicePropertyOriginalRadius, &radius);540 return UGStatusSuccess;
541 assert(status == UGStatusSuccess);541
542 return radius;542 case UGSlicePropertyCenterOfRotationX:
543}543 *reinterpret_cast<float*>(value) = d_->center_of_rotation_x_;
544544 return UGStatusSuccess;
545float grail_slice_get_center_of_rotation_x(const UGSlice slice) {545
546 float x;546 case UGSlicePropertyCenterOfRotationY:
547 UGStatus status = slice->GetProperty(UGSlicePropertyCenterOfRotationX, &x);547 *reinterpret_cast<float*>(value) = d_->center_of_rotation_y_;
548 assert(status == UGStatusSuccess);548 return UGStatusSuccess;
549 return x;549 default:
550}550 break;
551551 }
552float grail_slice_get_center_of_rotation_y(const UGSlice slice) {552
553 float y;553 return UGStatusErrorUnknownProperty;
554 UGStatus status = slice->GetProperty(UGSlicePropertyCenterOfRotationY, &y);554 }
555 assert(status == UGStatusSuccess);555
556 return y;556 void UGSlice::ReferenceGesture() {
557}557 d_->gesture_ref_ = d_->gesture_.lock();
558558 }
559const UGTransform *grail_slice_get_transform(const UGSlice slice) {559
560 UGTransform *transform;560 uint64_t UGSlice::time() const {
561 UGStatus status = slice->GetProperty(UGSlicePropertyTransform, &transform);561 return d_->time_;
562 assert(status == UGStatusSuccess);562 }
563 return transform;563
564}564 const TouchSet & UGSlice::touches() {
565565 return d_->touches_;
566const UGTransform *grail_slice_get_cumulative_transform(const UGSlice slice) {566 }
567 UGTransform *transform;567
568 UGStatus status = slice->GetProperty(UGSlicePropertyCumulativeTransform,568 const UFFrame & UGSlice::frame() {
569 &transform);569 return d_->frame_;
570 assert(status == UGStatusSuccess);570 }
571 return transform;571
572}572 UGGestureState UGSlice::state() const {
573573 return d_->state_;
574const UFFrame grail_slice_get_frame(const UGSlice slice) {574 }
575 UFFrame frame;575
576 UGStatus status = slice->GetProperty(UGSlicePropertyFrame, &frame);576 void UGSlice::set_state( UGGestureState state ) {
577 assert(status == UGStatusSuccess);577 d_->state_ = state;
578 return frame;578 }
579}579
580580 }
581} // extern "C"581 // extern "C" {
582
583 UGStatus grail_slice_get_property( const UGSlice slice,
584 UGSliceProperty property,
585 void* value) {
586 if( slice == NULL )
587 return( UGStatusErrorGeneric );
588
589 return static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(property, value);
590 }
591
592 unsigned int grail_slice_get_id(const UGSlice slice) {
593 if( slice == NULL )
594 return( UGStatusErrorGeneric );
595 unsigned int id;
596 UGStatus status = static_cast< const utouch::grail::UGSlice*>( slice )->GetProperty(UGSlicePropertyId, &id);
597 assert(status == UGStatusSuccess);
598 return id;
599 }
600
601 UGGestureState grail_slice_get_state(const UGSlice slice) {
602 assert( slice == NULL );
603 UGGestureState state;
604 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyState, &state);
605 assert(status == UGStatusSuccess);
606 return state;
607 }
608
609 UGGestureTypeMask grail_slice_get_recognized(const UGSlice slice) {
610 if( slice == NULL )
611 return( UGStatusErrorGeneric );
612
613 UGGestureTypeMask mask;
614 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyRecognized, &mask);
615 assert(status == UGStatusSuccess);
616 return mask;
617 }
618
619 UGSubscription grail_slice_get_subscription(const UGSlice slice) {
620 assert( slice == NULL );
621
622 UGSubscription subscription;
623 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertySubscription,
624 &subscription);
625 assert(status == UGStatusSuccess);
626 return subscription;
627 }
628
629 unsigned int grail_slice_get_num_touches(const UGSlice slice) {
630 assert( slice == NULL );
631
632 unsigned int num_touches;
633 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyNumTouches, &num_touches);
634 assert(status == UGStatusSuccess);
635 return num_touches;
636 }
637
638 UGStatus grail_slice_get_touch_id(const UGSlice slice, unsigned int index,
639 void *touch_id) {
640 if( slice == NULL )
641 return( UGStatusErrorGeneric );
642 return static_cast< const utouch::grail::UGSlice* >( slice )->GetTouchId(index, touch_id);
643 }
644
645 float grail_slice_get_original_center_x(const UGSlice slice) {
646 if( slice == NULL )
647 return( UGStatusErrorGeneric );
648 float x;
649 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalCenterX, &x);
650 assert(status == UGStatusSuccess);
651 return x;
652 }
653
654 float grail_slice_get_original_center_y(const UGSlice slice) {
655 if( slice == NULL )
656 return( UGStatusErrorGeneric );
657 float y;
658 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalCenterY, &y);
659 assert(status == UGStatusSuccess);
660 return y;
661 }
662
663 float grail_slice_get_original_radius(const UGSlice slice) {
664 if( slice == NULL )
665 return( UGStatusErrorGeneric );
666 float radius;
667 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalRadius, &radius);
668 assert(status == UGStatusSuccess);
669 return radius;
670 }
671
672 float grail_slice_get_center_of_rotation_x(const UGSlice slice) {
673 if( slice == NULL )
674 return( UGStatusErrorGeneric );
675 float x;
676 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCenterOfRotationX, &x);
677 assert(status == UGStatusSuccess);
678 return x;
679 }
680
681 float grail_slice_get_center_of_rotation_y(const UGSlice slice) {
682 if( slice == NULL )
683 return( UGStatusErrorGeneric );
684 float y;
685 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCenterOfRotationY, &y);
686 assert(status == UGStatusSuccess);
687 return y;
688 }
689
690 const UGTransform *grail_slice_get_transform(const UGSlice slice) {
691 assert( slice == NULL );
692
693 UGTransform *transform;
694 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyTransform, &transform);
695 assert(status == UGStatusSuccess);
696 return transform;
697 }
698
699 const UGTransform *grail_slice_get_cumulative_transform(const UGSlice slice) {
700 assert( slice == NULL );
701
702 UGTransform *transform;
703 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCumulativeTransform,
704 &transform);
705 assert(status == UGStatusSuccess);
706 return transform;
707 }
708
709 const UFFrame grail_slice_get_frame(const UGSlice slice) {
710 assert( slice == NULL );
711
712 UFFrame frame;
713 UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyFrame, &frame);
714 assert(status == UGStatusSuccess);
715 return frame;
716 }
717}
718// } // extern "C"
582719
=== modified file 'src/v3/slice.h'
--- src/v3/slice.h 2011-10-20 23:55:57 +0000
+++ src/v3/slice.h 2011-11-01 21:20:40 +0000
@@ -27,69 +27,61 @@
2727
28#include "utouch/grail.h"28#include "utouch/grail.h"
2929
30class Gesture;30namespace utouch {
3131 namespace grail {
32typedef std::shared_ptr<Gesture> SharedGesture;32
33typedef std::shared_ptr<UGSlice_> SharedUGSlice_;33 class Gesture;
34typedef std::set<unsigned int> TouchSet;34
3535 class UGSlice;
36class UGSlice_ {36 class UGSubscription;
37 public:37
38 static UGSlice_* NewUGSlice_(const SharedGesture& gesture, UFEvent event,38 typedef std::shared_ptr<Gesture> SharedGesture;
39 const TouchSet& touches,39 typedef std::shared_ptr<UGSlice> SharedUGSlice;
40 UGGestureTypeMask recognized);40 typedef std::set<unsigned int> TouchSet;
41 static UGSlice_* NewUGSlice_(const SharedUGSlice_& prev, UFEvent event,41
42 const TouchSet& touches);42 class UGSlice {
4343 public:
44 ~UGSlice_();44
4545 static UGSlice* NewUGSlice(const SharedGesture& gesture, UFEvent event,
46 void CheckGestureEnd();46 const TouchSet& touches,
47 UGGestureTypeMask CheckRecognition(const UGSubscription_& subscription);47 UGGestureTypeMask recognized);
48 UGStatus GetTouchId(unsigned int index, void* touch_id) const;48 static UGSlice* NewUGSlice(const SharedUGSlice& prev, UFEvent event,
49 UGStatus GetProperty(UGSliceProperty property, void* value) const;49 const TouchSet& touches);
50 void ReferenceGesture() { gesture_ref_ = gesture_.lock(); }50
5151 void CheckGestureEnd();
52 uint64_t time() const { return time_; }52
53 const TouchSet& touches() { return touches_; }53 UGGestureTypeMask CheckRecognition( const UGSubscription & subscription );
54 const UFFrame& frame() { return frame_; }54
55 UGGestureState state() const { return state_; }55 UGStatus GetTouchId(unsigned int index, void* touch_id) const;
56 void set_state(UGGestureState state) { state_ = state; }56
5757 UGStatus GetProperty(UGSliceProperty property, void* value) const;
58 UGSlice_(const UGSlice_&) = delete;58
59 void operator=(const UGSlice_&) = delete;59 void ReferenceGesture();
6060
61 private:61 uint64_t time() const;
62 const std::weak_ptr<Gesture> gesture_;62 const TouchSet& touches();
63 SharedGesture gesture_ref_;63 const UFFrame& frame();
64 const UFEvent event_;64 UGGestureState state() const;
65 UFFrame frame_;65 void set_state( UGGestureState state );
66 TouchSet touches_;66
67 uint64_t time_;67 // Disable compiler generated c'tor, copy c'tor and assignment operator.
68 UGGestureState state_;68 UGSlice( const UGSlice & ) = delete;
69 float original_center_x_;69 // void operator=( const UGSlice & ) = delete;
70 float original_center_y_;70 bool operator==( const UGSlice & ) const = delete;
71 float original_radius_;71
72 float original_angle_;72 protected:
73 float radius_;73 struct Private;
74 float angle_;74 std::shared_ptr< Private > d_;
75 float transform_[3][3];75
76 float cumulative_transform_[3][3];76 UGSlice( const SharedGesture & gesture,
77 float center_of_rotation_x_;77 UFEvent event,
78 float center_of_rotation_y_;78 const TouchSet & touches,
79 UGGestureTypeMask recognized_;79 UGGestureTypeMask recognized);
80 bool touch_count_changed_;80
8181 UGSlice( const SharedUGSlice & prev,
82 UGSlice_(const SharedGesture& gesture, UFEvent event, const TouchSet& touches,82 UFEvent event,
83 UGGestureTypeMask recognized);83 const TouchSet& touches );
84 UGSlice_(const SharedUGSlice_& prev, UFEvent event, const TouchSet& touches);84 };
8585 }
86 void GetValues(const TouchSet& touches, float* x, float* y, float* radius,86}
87 float* angle, bool init);
88 void SetTransforms();
89 void SetCenterOfRotation();
90 uint64_t CumulativeTime() const;
91 float CumulativeDrag2() const;
92 float CumulativePinch() const;
93};
94
95#endif // UTOUCH_GRAIL_SLICE_H_87#endif // UTOUCH_GRAIL_SLICE_H_
9688
=== modified file 'src/v3/subscription.cpp'
--- src/v3/subscription.cpp 2011-10-20 16:00:48 +0000
+++ src/v3/subscription.cpp 2011-11-01 21:20:40 +0000
@@ -21,265 +21,303 @@
2121
22#include "v3/subscription.h"22#include "v3/subscription.h"
2323
24#include <math.h>24#include <cassert>
2525#include <cmath>
26Limit::Limit(UGGestureType type) {26
27 switch (type) {27namespace utouch {
28 case UGGestureTypeDrag:28 namespace grail {
29 timeout_ = 300;29
30 threshold_ = 2.6;30 UGSubscription::Limit::Limit(UGGestureType type) {
31 break;31 switch (type) {
3232 case UGGestureTypeDrag:
33 case UGGestureTypePinch:33 timeout_ = 300;
34 timeout_ = 300;34 threshold_ = 2.6;
35 threshold_ = 1.1; /* Different from grail v1, ratio instead of delta */35 break;
36 break;36
3737 case UGGestureTypePinch:
38 case UGGestureTypeRotate:38 timeout_ = 300;
39 timeout_ = 500;39 threshold_ = 1.1; /* Different from grail v1, ratio instead of delta */
40 threshold_ = 2 * M_PI / 50;40 break;
41 break;41
4242 case UGGestureTypeRotate:
43 case UGGestureTypeTap:43 timeout_ = 500;
44 timeout_ = 300;44 threshold_ = 2 * M_PI / 50;
45 threshold_ = 0;45 break;
46 break;46
4747 case UGGestureTypeTap:
48 case UGGestureTypeTouch:48 timeout_ = 300;
49 timeout_ = 0;49 threshold_ = 0;
50 threshold_ = 0;50 break;
51 break;51
52 }52 case UGGestureTypeTouch:
53}53 timeout_ = 0;
5454 threshold_ = 0;
55UGSubscription_::UGSubscription_()55 break;
56 : device_(0),56 }
57 window_(0),57 }
58 mask_(0),58
59 touches_start_(2),59 struct UGSubscription::Private {
60 touches_min_(0),60
61 touches_max_(0),61 Private() : device_(0),
62 drag_(UGGestureTypeDrag),62 window_(0),
63 pinch_(UGGestureTypePinch),63 mask_(0),
64 rotate_(UGGestureTypeRotate),64 touches_start_(2),
65 tap_(UGGestureTypeTap) {65 touches_min_(0),
66}66 touches_max_(0),
6767 drag_(UGGestureTypeDrag),
68bool UGSubscription_::IsValid() const {68 pinch_(UGGestureTypePinch),
69 if (!device_ ||69 rotate_(UGGestureTypeRotate),
70 !window_ ||70 tap_(UGGestureTypeTap) {
71 mask_ == 0 ||71 }
72 (touches_max_ && touches_start_ > touches_max_) ||72
73 (touches_min_ && touches_start_ < touches_min_))73 UFDevice device_;
74 return false;74 Window window_;
7575 UGGestureTypeMask mask_;
76 return true;76 unsigned int touches_start_;
77}77 unsigned int touches_min_;
7878 unsigned int touches_max_;
79UGStatus UGSubscription_::SetProperty(UGSubscriptionProperty property,79 Limit drag_;
80 const void* value) {80 Limit pinch_;
81 switch (property) {81 Limit rotate_;
82 case UGSubscriptionPropertyDevice: {82 Limit tap_;
83 UFDevice device = *reinterpret_cast<const UFDevice*>(value);83 };
84 if (!device)84
85 return UGStatusErrorInvalidValue;85 UGSubscription::UGSubscription()
86 device_ = device;86 : d_( new Private() ) {
87 return UGStatusSuccess;87 }
88 }88
8989 bool UGSubscription::IsValid() const {
90 case UGSubscriptionPropertyWindow: {90 if (!d_->device_ ||
91 Window window = *reinterpret_cast<const Window*>(value);91 !d_->window_ ||
92 if (!window)92 d_->mask_ == 0 ||
93 return UGStatusErrorInvalidValue;93 (d_->touches_max_ && d_->touches_start_ > d_->touches_max_) ||
94 window_ = window;94 (d_->touches_min_ && d_->touches_start_ < d_->touches_min_))
95 return UGStatusSuccess;95 return false;
96 }96
9797 return true;
98 case UGSubscriptionPropertyMask: {98 }
99 UGGestureTypeMask mask =99
100 *reinterpret_cast<const UGGestureTypeMask*>(value);100 UGStatus UGSubscription::SetProperty(UGSubscriptionProperty property,
101 if (mask == 0)101 const void* value) {
102 return UGStatusErrorInvalidValue;102
103 mask_ = mask;103 assert( value == NULL );
104 return UGStatusSuccess;104
105 }105 switch (property) {
106106 case UGSubscriptionPropertyDevice: {
107 case UGSubscriptionPropertyTouchesStart: {107 UFDevice device = *reinterpret_cast<const UFDevice*>(value);
108 unsigned int touches = *reinterpret_cast<const unsigned int*>(value);108 if (!device)
109 if (touches == 0 || touches > 5)109 return UGStatusErrorInvalidValue;
110 return UGStatusErrorInvalidValue;110 d_->device_ = device;
111 touches_start_ = touches;111 return UGStatusSuccess;
112 return UGStatusSuccess;112 }
113 }113
114114 case UGSubscriptionPropertyWindow: {
115 case UGSubscriptionPropertyTouchesMinimum: {115 Window window = *reinterpret_cast<const Window*>(value);
116 unsigned int touches = *reinterpret_cast<const unsigned int*>(value);116 if (!window)
117 if (touches == 0 || touches > 5)117 return UGStatusErrorInvalidValue;
118 return UGStatusErrorInvalidValue;118 d_->window_ = window;
119 touches_min_ = touches;119 return UGStatusSuccess;
120 return UGStatusSuccess;120 }
121 }121
122122 case UGSubscriptionPropertyMask: {
123 case UGSubscriptionPropertyTouchesMaximum: {123 UGGestureTypeMask mask =
124 unsigned int touches = *reinterpret_cast<const unsigned int*>(value);124 *reinterpret_cast<const UGGestureTypeMask*>(value);
125 if (touches == 0 || touches > 5)125 if (mask == 0)
126 return UGStatusErrorInvalidValue;126 return UGStatusErrorInvalidValue;
127 touches_max_ = touches;127 d_->mask_ = mask;
128 return UGStatusSuccess;128 return UGStatusSuccess;
129 }129 }
130130
131 case UGSubscriptionPropertyDragTimeout: {131 case UGSubscriptionPropertyTouchesStart: {
132 uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);132 unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
133 if (timeout < 0)133 if (touches == 0 || touches > 5)
134 return UGStatusErrorInvalidValue;134 return UGStatusErrorInvalidValue;
135 drag_.set_timeout(timeout);135 d_->touches_start_ = touches;
136 return UGStatusSuccess;136 return UGStatusSuccess;
137 }137 }
138138
139 case UGSubscriptionPropertyDragThreshold: {139 case UGSubscriptionPropertyTouchesMinimum: {
140 float threshold = *reinterpret_cast<const float*>(value);140 unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
141 if (threshold < 0)141 if (touches == 0 || touches > 5)
142 return UGStatusErrorInvalidValue;142 return UGStatusErrorInvalidValue;
143 drag_.set_threshold(threshold);143 d_->touches_min_ = touches;
144 return UGStatusSuccess;144 return UGStatusSuccess;
145 }145 }
146146
147 case UGSubscriptionPropertyPinchTimeout: {147 case UGSubscriptionPropertyTouchesMaximum: {
148 uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);148 unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
149 if (timeout < 0)149 if (touches == 0 || touches > 5)
150 return UGStatusErrorInvalidValue;150 return UGStatusErrorInvalidValue;
151 pinch_.set_timeout(timeout);151 d_->touches_max_ = touches;
152 return UGStatusSuccess;152 return UGStatusSuccess;
153 }153 }
154154
155 case UGSubscriptionPropertyPinchThreshold: {155 case UGSubscriptionPropertyDragTimeout: {
156 float threshold = *reinterpret_cast<const float*>(value);156 uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
157 if (threshold < 0)157 if (timeout < 0)
158 return UGStatusErrorInvalidValue;158 return UGStatusErrorInvalidValue;
159 pinch_.set_threshold(threshold);159 d_->drag_.timeout_ = timeout;
160 return UGStatusSuccess;160 return UGStatusSuccess;
161 }161 }
162162
163 case UGSubscriptionPropertyRotateTimeout: {163 case UGSubscriptionPropertyDragThreshold: {
164 uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);164 float threshold = *reinterpret_cast<const float*>(value);
165 if (timeout < 0)165 if (threshold < 0)
166 return UGStatusErrorInvalidValue;166 return UGStatusErrorInvalidValue;
167 rotate_.set_timeout(timeout);167 d_->drag_.threshold_ = threshold;
168 return UGStatusSuccess;168 return UGStatusSuccess;
169 }169 }
170170
171 case UGSubscriptionPropertyRotateThreshold: {171 case UGSubscriptionPropertyPinchTimeout: {
172 float threshold = *reinterpret_cast<const float*>(value);172 uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
173 if (threshold < 0)173 if (timeout < 0)
174 return UGStatusErrorInvalidValue;174 return UGStatusErrorInvalidValue;
175 rotate_.set_threshold(threshold);175 d_->pinch_.timeout_ = timeout;
176 return UGStatusSuccess;176 return UGStatusSuccess;
177 }177 }
178178
179 case UGSubscriptionPropertyTapTimeout: {179 case UGSubscriptionPropertyPinchThreshold: {
180 uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);180 float threshold = *reinterpret_cast<const float*>(value);
181 if (timeout < 0)181 if (threshold < 0)
182 return UGStatusErrorInvalidValue;182 return UGStatusErrorInvalidValue;
183 tap_.set_timeout(timeout);183 d_->pinch_.threshold_ = threshold;
184 return UGStatusSuccess;184 return UGStatusSuccess;
185 }185 }
186186
187 case UGSubscriptionPropertyTapThreshold: {187 case UGSubscriptionPropertyRotateTimeout: {
188 float threshold = *reinterpret_cast<const float*>(value);188 uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
189 if (threshold < 0)189 if (timeout < 0)
190 return UGStatusErrorInvalidValue;190 return UGStatusErrorInvalidValue;
191 tap_.set_threshold(threshold);191 d_->rotate_.timeout_ = timeout;
192 return UGStatusSuccess;192 return UGStatusSuccess;
193 }193 }
194 }194
195195 case UGSubscriptionPropertyRotateThreshold: {
196 return UGStatusErrorUnknownProperty;196 float threshold = *reinterpret_cast<const float*>(value);
197}197 if (threshold < 0)
198198 return UGStatusErrorInvalidValue;
199UGStatus UGSubscription_::GetProperty(UGSubscriptionProperty property,199 d_->rotate_.threshold_ = threshold;
200 void* value) const {200 return UGStatusSuccess;
201 switch (property) {201 }
202 case UGSubscriptionPropertyDevice:202
203 *reinterpret_cast<UFDevice*>(value) = device_;203 case UGSubscriptionPropertyTapTimeout: {
204 return UGStatusSuccess;204 uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
205205 if (timeout < 0)
206 case UGSubscriptionPropertyWindow:206 return UGStatusErrorInvalidValue;
207 *reinterpret_cast<Window*>(value) = window_;207 d_->tap_.timeout_ = timeout;
208 return UGStatusSuccess;208 return UGStatusSuccess;
209209 }
210 case UGSubscriptionPropertyMask:210
211 *reinterpret_cast<UGGestureTypeMask*>(value) = mask_;211 case UGSubscriptionPropertyTapThreshold: {
212 return UGStatusSuccess;212 float threshold = *reinterpret_cast<const float*>(value);
213213 if (threshold < 0)
214 case UGSubscriptionPropertyTouchesStart:214 return UGStatusErrorInvalidValue;
215 *reinterpret_cast<unsigned int*>(value) = touches_start_;215 d_->tap_.threshold_ = threshold;
216 return UGStatusSuccess;216 return UGStatusSuccess;
217217 }
218 case UGSubscriptionPropertyTouchesMinimum:218 }
219 *reinterpret_cast<unsigned int*>(value) = touches_min_;219
220 return UGStatusSuccess;220 return UGStatusErrorUnknownProperty;
221221 }
222 case UGSubscriptionPropertyTouchesMaximum:222
223 *reinterpret_cast<unsigned int*>(value) = touches_max_;223 UGStatus UGSubscription::GetProperty(UGSubscriptionProperty property,
224 return UGStatusSuccess;224 void* value) const {
225225 assert( value == NULL );
226 case UGSubscriptionPropertyDragTimeout:226 switch (property) {
227 *reinterpret_cast<uint64_t*>(value) = drag_.timeout();227 case UGSubscriptionPropertyDevice:
228 return UGStatusSuccess;228 *reinterpret_cast<UFDevice*>(value) = d_->device_;
229229 return UGStatusSuccess;
230 case UGSubscriptionPropertyDragThreshold:230
231 *reinterpret_cast<float*>(value) = drag_.threshold();231 case UGSubscriptionPropertyWindow:
232 return UGStatusSuccess;232 *reinterpret_cast<Window*>(value) = d_->window_;
233233 return UGStatusSuccess;
234 case UGSubscriptionPropertyPinchTimeout:234
235 *reinterpret_cast<uint64_t*>(value) = pinch_.timeout();235 case UGSubscriptionPropertyMask:
236 return UGStatusSuccess;236 *reinterpret_cast<UGGestureTypeMask*>(value) = d_->mask_;
237237 return UGStatusSuccess;
238 case UGSubscriptionPropertyPinchThreshold:238
239 *reinterpret_cast<float*>(value) = pinch_.threshold();239 case UGSubscriptionPropertyTouchesStart:
240 return UGStatusSuccess;240 *reinterpret_cast<unsigned int*>(value) = d_->touches_start_;
241241 return UGStatusSuccess;
242 case UGSubscriptionPropertyRotateTimeout:242
243 *reinterpret_cast<uint64_t*>(value) = rotate_.timeout();243 case UGSubscriptionPropertyTouchesMinimum:
244 return UGStatusSuccess;244 *reinterpret_cast<unsigned int*>(value) = d_->touches_min_;
245245 return UGStatusSuccess;
246 case UGSubscriptionPropertyRotateThreshold:246
247 *reinterpret_cast<float*>(value) = rotate_.threshold();247 case UGSubscriptionPropertyTouchesMaximum:
248 return UGStatusSuccess;248 *reinterpret_cast<unsigned int*>(value) = d_->touches_max_;
249249 return UGStatusSuccess;
250 case UGSubscriptionPropertyTapTimeout:250
251 *reinterpret_cast<uint64_t*>(value) = tap_.timeout();251 case UGSubscriptionPropertyDragTimeout:
252 return UGStatusSuccess;252 *reinterpret_cast<uint64_t*>(value) = d_->drag_.timeout_;
253253 return UGStatusSuccess;
254 case UGSubscriptionPropertyTapThreshold:254
255 *reinterpret_cast<float*>(value) = tap_.threshold();255 case UGSubscriptionPropertyDragThreshold:
256 return UGStatusSuccess;256 *reinterpret_cast<float*>(value) = d_->drag_.threshold_;
257 }257 return UGStatusSuccess;
258258
259 return UGStatusErrorUnknownProperty;259 case UGSubscriptionPropertyPinchTimeout:
260}260 *reinterpret_cast<uint64_t*>(value) = d_->pinch_.timeout_;
261261 return UGStatusSuccess;
262extern "C" {262
263263 case UGSubscriptionPropertyPinchThreshold:
264UGStatus grail_subscription_new(UGSubscription* subscription) {264 *reinterpret_cast<float*>(value) = d_->pinch_.threshold_;
265 *subscription = new UGSubscription_;265 return UGStatusSuccess;
266 return UGStatusSuccess;266
267 case UGSubscriptionPropertyRotateTimeout:
268 *reinterpret_cast<uint64_t*>(value) = d_->rotate_.timeout_;
269 return UGStatusSuccess;
270
271 case UGSubscriptionPropertyRotateThreshold:
272 *reinterpret_cast<float*>(value) = d_->rotate_.threshold_;
273 return UGStatusSuccess;
274
275 case UGSubscriptionPropertyTapTimeout:
276 *reinterpret_cast<uint64_t*>(value) = d_->tap_.timeout_;
277 return UGStatusSuccess;
278
279 case UGSubscriptionPropertyTapThreshold:
280 *reinterpret_cast<float*>(value) = d_->tap_.threshold_;
281 return UGStatusSuccess;
282 }
283
284 return UGStatusErrorUnknownProperty;
285 }
286
287 UFDevice UGSubscription::device() const { return d_->device_; }
288 Window UGSubscription::window() const { return d_->window_; }
289 UGGestureTypeMask UGSubscription::mask() const { return d_->mask_; }
290 unsigned int UGSubscription::touches_start() const { return d_->touches_start_; }
291 unsigned int UGSubscription::touches_min() const { return d_->touches_min_; }
292 unsigned int UGSubscription::touches_max() const { return d_->touches_max_; }
293
294 const UGSubscription::Limit & UGSubscription::drag() const { return d_->drag_; }
295 const UGSubscription::Limit & UGSubscription::pinch() const { return d_->pinch_; }
296 const UGSubscription::Limit & UGSubscription::rotate() const { return d_->rotate_; }
297 const UGSubscription::Limit & UGSubscription::tap() const { return d_->tap_; }
298 }
299}
300// extern "C" {
301
302UGStatus grail_subscription_new(UGSubscription * subscription) {
303 *subscription = new UGSubscription();
304 return UGStatusSuccess;
267}305}
268306
269void grail_subscription_delete(UGSubscription subscription) {307void grail_subscription_delete(UGSubscription subscription) {
270 delete subscription;308 delete( static_cast< utouch::grail::UGSubscription* >( subscription ) );
271}309}
272310
273UGStatus grail_subscription_set_property(UGSubscription subscription,311UGStatus grail_subscription_set_property( UGSubscription subscription,
274 UGSubscriptionProperty property,312 UGSubscriptionProperty property,
275 const void* value) {313 const void* value) {
276 return subscription->SetProperty(property, value);314 return( static_cast< utouch::grail::UGSubscription* >( subscription )->SetProperty(property, value ) );
277}315}
278316
279UGStatus grail_subscription_get_property(UGSubscription subscription,317UGStatus grail_subscription_get_property(UGSubscription subscription,
280 UGSubscriptionProperty property,318 UGSubscriptionProperty property,
281 void* value) {319 void* value) {
282 return subscription->GetProperty(property, value);320 return( static_cast< utouch::grail::UGSubscription* >( subscription )->GetProperty(property, value) );
283}321}
284322
285} // extern "C"323// } // extern "C"
286324
=== modified file 'src/v3/subscription.h'
--- src/v3/subscription.h 2011-10-12 23:36:27 +0000
+++ src/v3/subscription.h 2011-11-01 21:20:40 +0000
@@ -26,58 +26,47 @@
2626
27#include "utouch/grail.h"27#include "utouch/grail.h"
2828
29class Limit {29#include <memory>
30 public:30
31 explicit Limit(UGGestureType type);31namespace utouch {
3232 namespace grail {
33 uint64_t timeout() const { return timeout_; }33
34 float threshold() const { return threshold_; }34 class UGSubscription {
3535 public:
36 Limit(const Limit&) = delete;36
37 void operator=(const Limit&) = delete;37 struct Limit {
3838 explicit Limit( UGGestureType type );
39 private:39
40 void set_timeout(uint64_t timeout) { timeout_ = timeout; }40 uint64_t timeout_;
41 void set_threshold(float threshold) { threshold_ = threshold; }41 float threshold_;
42 uint64_t timeout_;42 };
43 float threshold_;43
4444 UGSubscription();
45 friend class UGSubscription_;45
46};46 bool IsValid() const;
4747
48class UGSubscription_ {48 UGStatus SetProperty(UGSubscriptionProperty property, const void* value);
49 public:49 UGStatus GetProperty(UGSubscriptionProperty property, void* value) const;
50 UGSubscription_();50
5151 UFDevice device() const;
52 bool IsValid() const;52 Window window() const;
53 UGStatus SetProperty(UGSubscriptionProperty property, const void* value);53 UGGestureTypeMask mask() const;
54 UGStatus GetProperty(UGSubscriptionProperty property, void* value) const;54 unsigned int touches_start() const;
5555 unsigned int touches_min() const;
56 UFDevice device() const { return device_; }56 unsigned int touches_max() const;
57 Window window() const { return window_; }57
58 UGGestureTypeMask mask() const { return mask_; }58 const Limit & drag() const;
59 unsigned int touches_start() const { return touches_start_; }59 const Limit & pinch() const;
60 unsigned int touches_min() const { return touches_min_; }60 const Limit & rotate() const;
61 unsigned int touches_max() const { return touches_max_; }61 const Limit & tap() const;
62 const Limit& drag() const { return drag_; }62
63 const Limit& pinch() const { return pinch_; }63 UGSubscription(const UGSubscription & ) = delete;
64 const Limit& rotate() const { return rotate_; }64 UGSubscription & operator=(const UGSubscription & ) = delete;
65 const Limit& tap() const { return tap_; }65
6666 protected:
67 UGSubscription_(const UGSubscription_&) = delete;67 struct Private;
68 void operator=(const UGSubscription_&) = delete;68 std::shared_ptr< Private > d_;
6969 };
70 private:70 }
71 UFDevice device_;71}
72 Window window_;
73 UGGestureTypeMask mask_;
74 unsigned int touches_start_;
75 unsigned int touches_min_;
76 unsigned int touches_max_;
77 Limit drag_;
78 Limit pinch_;
79 Limit rotate_;
80 Limit tap_;
81};
82
83#endif // UTOUCH_GRAIL_SUBSCRIPTION_H_72#endif // UTOUCH_GRAIL_SUBSCRIPTION_H_

Subscribers

People subscribed via source and target branches

to all changes: