Merge lp:~thomas-voss/grail/rework_cosmetics into lp:~chasedouglas/grail/rework

Proposed by Thomas Voß on 2011-11-01
Status: Rejected
Rejected by: Chase Douglas on 2011-11-22
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 on 2011-11-03
Chase Douglas 2011-11-01 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.
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ß on 2011-10-31

Modified: Reverted changes to initialization of limits.

240. By Thomas Voß on 2011-10-31

Cleaned up v3, introduced utouch::grail namespace and PIMPL-ed classes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/utouch/grail.h'
2--- include/utouch/grail.h 2011-10-19 21:39:17 +0000
3+++ include/utouch/grail.h 2011-11-01 21:20:40 +0000
4@@ -41,13 +41,13 @@
5 */
6
7 /** An object for the context of the uTouch Frame instance */
8-typedef struct UGHandle_* UGHandle;
9+typedef void * UGHandle;
10 /** An object for a gesture subscription */
11-typedef struct UGSubscription_* UGSubscription;
12+typedef void * UGSubscription;
13 /** An object for an event */
14-typedef const struct UGEvent_* UGEvent;
15+typedef const void * UGEvent;
16 /** An object for a gesture state in time */
17-typedef const struct UGSlice_* UGSlice;
18+typedef void * UGSlice;
19
20 /** The status code denoting the result of a function call */
21 typedef enum UGStatus {
22@@ -400,7 +400,7 @@
23 * @param [out] event The retrieved event
24 * @return UGStatusSuccess or UGStatusErrorNoEvent
25 */
26-UGStatus grail_get_event(UGHandle handle, UGEvent *event);
27+UGStatus grail_get_event(UGHandle handle, UGEvent * event );
28
29 /**
30 * Release an event back to the uTouch Grail context
31@@ -499,7 +499,7 @@
32 * @param [in] event The event object
33 * @return The type of the event
34 */
35-UGEventType grail_event_get_type(const UGEvent event);
36+UGEventType grail_event_get_type( UGEvent event);
37
38 /**
39 * Get the time of an event
40@@ -507,7 +507,7 @@
41 * @param [in] event The event object
42 * @return The time of the event
43 */
44-uint64_t grail_event_get_time(const UGEvent event);
45+uint64_t grail_event_get_time(UGEvent event);
46
47 /**
48 * Get the ID of a gesture from a slice
49
50=== modified file 'src/v3/event.cpp'
51--- src/v3/event.cpp 2011-10-13 22:56:46 +0000
52+++ src/v3/event.cpp 2011-11-01 21:20:40 +0000
53@@ -1,6 +1,6 @@
54 /*****************************************************************************
55 *
56- * utouch-grail - Multitouch Gesture Recognition Library
57+ * Utouch-grail - Multitouch Gesture Recognition Library
58 *
59 * Copyright (C) 2011 Canonical Ltd.
60 *
61@@ -21,52 +21,71 @@
62
63 #include "event.h"
64
65-#include <assert.h>
66+#include <cassert>
67
68 #include "slice.h"
69
70-UGEvent_::UGEvent_(const SharedUGSlice_& slice)
71- : slice_(slice),
72- time_(slice->time()) {
73-}
74-
75-UGStatus UGEvent_::GetProperty(UGEventProperty property, void* data) const {
76- switch (property) {
77- case UGEventPropertyType:
78- *reinterpret_cast<UGEventType*>(data) = UGEventTypeSlice;
79- return UGStatusSuccess;
80-
81- case UGEventPropertySlice:
82- *reinterpret_cast<UGSlice*>(data) = slice_.get();
83- return UGStatusSuccess;
84-
85- case UGEventPropertyTime:
86- *reinterpret_cast<uint64_t*>(data) = time_;
87- return UGStatusSuccess;
88- }
89-
90- return UGStatusErrorUnknownProperty;
91-}
92-
93-extern "C" {
94+namespace utouch {
95+ namespace grail {
96+
97+ struct UGEvent::Private {
98+
99+ Private( const SharedUGSlice & slice ) : slice_( slice ),
100+ time_( slice->time() ) {
101+ }
102+
103+ const SharedUGSlice slice_;
104+ const uint64_t time_;
105+ };
106+
107+ UGEvent::UGEvent(const SharedUGSlice & slice)
108+ : d_( new Private( slice ) ) {
109+ }
110+
111+ UGStatus UGEvent::GetProperty(UGEventProperty property, void* data) const {
112+ assert( data == NULL );
113+
114+ switch (property) {
115+ case UGEventPropertyType:
116+ *reinterpret_cast<UGEventType*>(data) = UGEventTypeSlice;
117+ return UGStatusSuccess;
118+
119+ case UGEventPropertySlice:
120+ *reinterpret_cast<UGSlice*>(data) = *d_->slice_.get();
121+ return UGStatusSuccess;
122+
123+ case UGEventPropertyTime:
124+ *reinterpret_cast<uint64_t*>(data) = d_->time_;
125+ return UGStatusSuccess;
126+ }
127+
128+ return UGStatusErrorUnknownProperty;
129+ }
130+ }
131+
132+}
133
134 UGStatus grail_event_get_property(const UGEvent event, UGEventProperty property,
135 void* data) {
136- return event->GetProperty(property, data);
137+ assert( event == NULL );
138+ assert( data == NULL );
139+
140+ return static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(property, data);
141 }
142
143 UGEventType grail_event_get_type(const UGEvent event) {
144- UGEventType type;
145- UGStatus status = event->GetProperty(UGEventPropertyType, &type);
146- assert(status == UGStatusSuccess);
147- return type;
148+ assert( event == NULL );
149+ UGEventType type;
150+ UGStatus status = static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(UGEventPropertyType, &type);
151+ assert(status == UGStatusSuccess);
152+ return type;
153 }
154
155 uint64_t grail_event_get_time(const UGEvent event) {
156- uint64_t time;
157- UGStatus status = event->GetProperty(UGEventPropertyTime, &time);
158- assert(status == UGStatusSuccess);
159- return time;
160+ assert( event == NULL );
161+ uint64_t time;
162+ UGStatus status = static_cast< const utouch::grail::UGEvent* >( event )->GetProperty(UGEventPropertyTime, &time);
163+ assert(status == UGStatusSuccess);
164+ return time;
165 }
166
167-} // extern "C"
168
169=== modified file 'src/v3/event.h'
170--- src/v3/event.h 2011-10-13 22:56:46 +0000
171+++ src/v3/event.h 2011-11-01 21:20:40 +0000
172@@ -24,26 +24,31 @@
173
174 #include <memory>
175
176-#include <stdint.h>
177+#include <cstdint>
178
179 #include "utouch/grail.h"
180
181-class UGSlice_;
182-
183-typedef std::shared_ptr<UGSlice_> SharedUGSlice_;
184-
185-class UGEvent_ {
186- public:
187- UGEvent_(const SharedUGSlice_& slice);
188-
189- UGStatus GetProperty(UGEventProperty property, void* value) const;
190-
191- UGEvent_(const UGEvent_&) = delete;
192- void operator=(const UGEvent_&) = delete;
193-
194- private:
195- const SharedUGSlice_ slice_;
196- const uint64_t time_;
197-};
198-
199+namespace utouch {
200+ namespace grail {
201+
202+ class UGSlice;
203+
204+ typedef std::shared_ptr<UGSlice> SharedUGSlice;
205+
206+ class UGEvent {
207+ public:
208+ UGEvent(const SharedUGSlice & slice);
209+
210+ UGStatus GetProperty(UGEventProperty property, void* value) const;
211+
212+ UGEvent(const UGEvent&) = delete;
213+ void operator=(const UGEvent&) = delete;
214+
215+ protected:
216+ struct Private;
217+ std::shared_ptr< Private > d_;
218+
219+ };
220+ }
221+}
222 #endif // UTOUCH_GRAIL_EVENT_H
223
224=== modified file 'src/v3/gesture.cpp'
225--- src/v3/gesture.cpp 2011-10-20 22:19:11 +0000
226+++ src/v3/gesture.cpp 2011-11-01 21:20:40 +0000
227@@ -21,7 +21,7 @@
228
229 #include "gesture.h"
230
231-#include <stdio.h>
232+#include <cstdio>
233
234 #include "utouch/grail.h"
235
236@@ -30,184 +30,249 @@
237 #include "recognizer.h"
238 #include "slice.h"
239
240-Gesture::Gesture(Recognizer* recognizer, UGSubscription_* subscription,
241- TouchSet& touches, uint64_t start_time)
242- : recognizer_(recognizer),
243- id_(recognizer_->handle()->NewGestureID(recognizer_)),
244- subscription_(subscription),
245- touches_(touches),
246- start_time_(start_time),
247- recognized_(0),
248- canceled_(false),
249- ended_(false) {
250-}
251-
252-Gesture::Gesture(const Gesture* other_gesture, TouchSet& touches)
253- : recognizer_(other_gesture->recognizer_),
254- id_(recognizer_->handle()->NewGestureID(recognizer_)),
255- subscription_(other_gesture->subscription_),
256- touches_(touches),
257- start_time_(other_gesture->start_time_),
258- recognized_(other_gesture->recognized_),
259- canceled_(false),
260- ended_(false) {
261-}
262-
263-void Gesture::Update(UFEvent frame_event, TouchSet& modified_touches) {
264- if (ended_) {
265- if (recognized_ && IsOwned())
266- FlushSlices();
267-
268- return;
269- }
270-
271- UFFrame frame;
272- UFStatus status = frame_event_get_property(frame_event, UFEventPropertyFrame,
273- &frame);
274- if (status != UFStatusSuccess) {
275- fprintf(stderr, "Warning: failed to get frame from event\n");
276- return;
277- }
278-
279- TouchSet ended_touches;
280- bool touch_found = false;
281- for (unsigned int touch_id : modified_touches) {
282- if (touches_.find(touch_id) != touches_.end())
283- touch_found = true;
284- else
285- continue;
286-
287- UFTouch touch;
288- status = frame_frame_get_touch_by_id(frame, &touch_id, &touch);
289- if (status != UFStatusSuccess) {
290- fprintf(stderr, "Warning: failed to get touch from frame\n");
291- return;
292- }
293-
294- UFTouchState state = frame_touch_get_state(touch);
295- int owned;
296- status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned);
297- if (status != UFStatusSuccess) {
298- fprintf(stderr, "Warning: failed to get touch from frame\n");
299- return;
300- }
301-
302- if (state == UFTouchStateEnd) {
303- if (owned) {
304- ended_touches.insert(touch_id);
305- } else {
306- canceled_ = true;
307- break;
308- }
309- }
310- }
311-
312- if (!touch_found || canceled_)
313- return;
314-
315- if (!last_slice_) {
316- UGSlice_* slice = UGSlice_::NewUGSlice_(shared_from_this(), frame_event,
317- touches_, recognized_);
318- if (!slice)
319- return;
320- last_slice_ = SharedUGSlice_(slice);
321- } else {
322- UGSlice_* slice = UGSlice_::NewUGSlice_(last_slice_, frame_event, touches_);
323- if (!slice)
324- return;
325- last_slice_ = SharedUGSlice_(slice);
326- }
327-
328- slices_.push(last_slice_);
329-
330- for (unsigned int touch_id : ended_touches)
331- touches_.erase(touch_id);
332-
333- if (recognized_ != subscription_->mask())
334- recognized_ |= last_slice_->CheckRecognition(*subscription_);
335-
336- if (recognized_ && IsOwned())
337- FlushSlices();
338-
339- ended_ = (last_slice_->state() == UGGestureStateEnd);
340- if (ended_)
341- last_slice_.reset();
342-}
343-
344-bool Gesture::IsOwned() const {
345- /* The only way we could reach here and not have any slices in the queue is
346- * if we already flushed the queue, which is only done if we own the touches.
347- */
348- if (slices_.empty())
349- return true;
350-
351- for (unsigned int touch_id : slices_.front()->touches()) {
352- UFTouch touch;
353- UFStatus status = frame_frame_get_touch_by_id(slices_.back()->frame(),
354- &touch_id, &touch);
355- if (status != UFStatusSuccess) {
356- fprintf(stderr, "Warning: failed to get touch from frame\n");
357- return false;
358- }
359-
360- int owned;
361- status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned);
362- if (status != UFStatusSuccess) {
363- fprintf(stderr, "Warning: failed to get ownership property from touch\n");
364- return false;
365- }
366-
367- if (!owned)
368- return false;
369- }
370-
371- return true;
372-}
373-
374-void Gesture::FlushSlices() {
375- while (!slices_.empty()) {
376- UGEvent_* event = new UGEvent_(slices_.front());
377- slices_.front()->ReferenceGesture();
378- recognizer_->handle()->EnqueueEvent(event);
379- slices_.pop();
380- }
381-}
382-
383-uint64_t Gesture::Timeout() const {
384- if (recognized_)
385- return 0;
386-
387- uint64_t time = 0;
388- if ((subscription_->mask() & UGGestureTypeDrag) &&
389- subscription_->drag().timeout() > time)
390- time = subscription_->drag().timeout();
391- if ((subscription_->mask() & UGGestureTypePinch) &&
392- subscription_->pinch().timeout() > time)
393- time = subscription_->pinch().timeout();
394- if ((subscription_->mask() & UGGestureTypeRotate) &&
395- subscription_->rotate().timeout() > time)
396- time = subscription_->rotate().timeout();
397- if ((subscription_->mask() & UGGestureTypeTap) &&
398- subscription_->tap().timeout() > time)
399- time = subscription_->tap().timeout();
400-
401- return time;
402-}
403-
404-float Gesture::AngleForTouch(unsigned int touch_id) const {
405- auto it = angles_.find(touch_id);
406- if (it != angles_.end())
407- return it->second;
408-
409- return 0;
410-}
411-
412-void Gesture::SetAngleForTouch(unsigned int touch_id, float angle) {
413- angles_[touch_id] = angle;
414-}
415-
416-void Gesture::Cancel() {
417- while (!slices_.empty())
418- slices_.pop();
419- last_slice_.reset();
420+namespace utouch {
421+ namespace grail {
422+
423+ struct Gesture::Private {
424+
425+ Private( Recognizer * recognizer,
426+ utouch::grail::UGSubscription * subscription,
427+ TouchSet & touches,
428+ uint64_t start_time )
429+ : recognizer_(recognizer),
430+ id_(recognizer_->handle()->NewGestureID(recognizer_)),
431+ subscription_(subscription),
432+ touches_(touches),
433+ start_time_(start_time),
434+ recognized_(0),
435+ canceled_(false),
436+ ended_(false) {
437+ }
438+
439+ Private( const Gesture* other_gesture, TouchSet & touches )
440+ : recognizer_(other_gesture->d_->recognizer_),
441+ id_(recognizer_->handle()->NewGestureID(recognizer_)),
442+ subscription_(other_gesture->d_->subscription_),
443+ touches_(touches),
444+ start_time_(other_gesture->d_->start_time_),
445+ recognized_(other_gesture->d_->recognized_),
446+ canceled_(false),
447+ ended_(false) {
448+ }
449+
450+ Recognizer * recognizer_;
451+ unsigned int id_;
452+ utouch::grail::UGSubscription* subscription_;
453+ TouchSet touches_;
454+ uint64_t start_time_;
455+ UGGestureTypeMask recognized_;
456+ std::queue<utouch::grail::SharedUGSlice> slices_;
457+ utouch::grail::SharedUGSlice last_slice_;
458+ bool canceled_;
459+ bool ended_;
460+ std::map<unsigned int, float> angles_;
461+ };
462+
463+ Gesture::Gesture(Recognizer* recognizer, utouch::grail::UGSubscription* subscription,
464+ TouchSet& touches, uint64_t start_time)
465+ : d_( new Private( recognizer, subscription, touches, start_time ) ) {
466+ }
467+
468+ Gesture::Gesture(const Gesture* other_gesture, TouchSet& touches)
469+ : d_( new Private( other_gesture, touches ) ) {
470+ }
471+
472+ void Gesture::Update(UFEvent frame_event, TouchSet& modified_touches) {
473+ if ( d_->ended_) {
474+ if (d_->recognized_ && IsOwned())
475+ FlushSlices();
476+
477+ return;
478+ }
479+
480+ UFFrame frame;
481+ UFStatus status = frame_event_get_property(frame_event, UFEventPropertyFrame,
482+ &frame);
483+ if (status != UFStatusSuccess) {
484+ fprintf(stderr, "Warning: failed to get frame from event\n");
485+ return;
486+ }
487+
488+ TouchSet ended_touches;
489+ bool touch_found = false;
490+ for (unsigned int touch_id : modified_touches) {
491+ if (d_->touches_.find(touch_id) != d_->touches_.end())
492+ touch_found = true;
493+ else
494+ continue;
495+
496+ UFTouch touch;
497+ status = frame_frame_get_touch_by_id(frame, &touch_id, &touch);
498+ if (status != UFStatusSuccess) {
499+ fprintf(stderr, "Warning: failed to get touch from frame\n");
500+ return;
501+ }
502+
503+ UFTouchState state = frame_touch_get_state(touch);
504+ int owned;
505+ status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned);
506+ if (status != UFStatusSuccess) {
507+ fprintf(stderr, "Warning: failed to get touch from frame\n");
508+ return;
509+ }
510+
511+ if (state == UFTouchStateEnd) {
512+ if (owned) {
513+ ended_touches.insert(touch_id);
514+ } else {
515+ d_->canceled_ = true;
516+ break;
517+ }
518+ }
519+ }
520+
521+ if (!touch_found || d_->canceled_)
522+ return;
523+
524+ /* TODO
525+ if (!last_slice_) {
526+ utouch::grail::UGSlice * slice = utouch::grail::UGSlice::NewUGSlice( shared_from_this(),
527+ frame_event,
528+ touches_,
529+ recognized_
530+ );
531+
532+ if (!slice)
533+ return;
534+ last_slice_ = utouch::grail::SharedUGSlice(slice);
535+ } else {
536+ // TODO
537+ // utouch::grail::UGSlice * slice = utouch::grail::UGSlice::NewUGSlice(last_slice_, frame_event, touches_);
538+ if (!slice)
539+ return;
540+ last_slice_ = utouch::grail::SharedUGSlice(slice);
541+ }*/
542+
543+ d_->slices_.push(d_->last_slice_);
544+
545+ for (unsigned int touch_id : ended_touches)
546+ d_->touches_.erase(touch_id);
547+
548+ if ( d_->recognized_ != d_->subscription_->mask())
549+ d_->recognized_ |= d_->last_slice_->CheckRecognition(*d_->subscription_);
550+
551+ if (d_->recognized_ && IsOwned())
552+ FlushSlices();
553+
554+ d_->ended_ = (d_->last_slice_->state() == UGGestureStateEnd);
555+ if (d_->ended_)
556+ d_->last_slice_.reset();
557+ }
558+
559+ bool Gesture::IsOwned() const {
560+ /* The only way we could reach here and not have any slices in the queue is
561+ * if we already flushed the queue, which is only done if we own the touches.
562+ */
563+ if (d_->slices_.empty())
564+ return true;
565+
566+ for (unsigned int touch_id : d_->slices_.front()->touches()) {
567+ UFTouch touch;
568+ UFStatus status = frame_frame_get_touch_by_id(d_->slices_.back()->frame(),
569+ &touch_id, &touch);
570+ if (status != UFStatusSuccess) {
571+ fprintf(stderr, "Warning: failed to get touch from frame\n");
572+ return false;
573+ }
574+
575+ int owned;
576+ status = frame_touch_get_property(touch, UFTouchPropertyOwned, &owned);
577+ if (status != UFStatusSuccess) {
578+ fprintf(stderr, "Warning: failed to get ownership property from touch\n");
579+ return false;
580+ }
581+
582+ if (!owned)
583+ return false;
584+ }
585+
586+ return true;
587+ }
588+
589+ void Gesture::FlushSlices() {
590+ while (!d_->slices_.empty()) {
591+ utouch::grail::UGEvent * event = new utouch::grail::UGEvent(d_->slices_.front());
592+ d_->slices_.front()->ReferenceGesture();
593+ d_->recognizer_->handle()->EnqueueEvent(event);
594+ d_->slices_.pop();
595+ }
596+ }
597+
598+ uint64_t Gesture::Timeout() const {
599+ if (d_->recognized_)
600+ return 0;
601+
602+ uint64_t time = 0;
603+ if ((d_->subscription_->mask() & UGGestureTypeDrag) &&
604+ d_->subscription_->drag().timeout_ > time)
605+ time = d_->subscription_->drag().timeout_;
606+ if ((d_->subscription_->mask() & UGGestureTypePinch) &&
607+ d_->subscription_->pinch().timeout_ > time)
608+ time = d_->subscription_->pinch().timeout_;
609+ if ((d_->subscription_->mask() & UGGestureTypeRotate) &&
610+ d_->subscription_->rotate().timeout_ > time)
611+ time = d_->subscription_->rotate().timeout_;
612+ if ((d_->subscription_->mask() & UGGestureTypeTap) &&
613+ d_->subscription_->tap().timeout_ > time)
614+ time = d_->subscription_->tap().timeout_;
615+
616+ return time;
617+ }
618+
619+ float Gesture::AngleForTouch(unsigned int touch_id) const {
620+ auto it = d_->angles_.find(touch_id);
621+ if (it != d_->angles_.end())
622+ return it->second;
623+
624+ return 0;
625+ }
626+
627+ void Gesture::SetAngleForTouch(unsigned int touch_id, float angle) {
628+ d_->angles_[touch_id] = angle;
629+ }
630+
631+ void Gesture::Cancel() {
632+ while (!d_->slices_.empty())
633+ d_->slices_.pop();
634+ d_->last_slice_.reset();
635+ }
636+
637+ const unsigned int Gesture::id() const {
638+ return d_->id_;
639+ }
640+
641+ const Recognizer & Gesture::recognizer() const {
642+ return *d_->recognizer_;
643+ }
644+
645+ utouch::grail::UGSubscription* Gesture::subscription() const {
646+ return d_->subscription_;
647+ }
648+
649+ const TouchSet& Gesture::touches() const {
650+ return d_->touches_;
651+ }
652+
653+ const uint64_t Gesture::start_time() const {
654+ return d_->start_time_;
655+ }
656+
657+ bool Gesture::canceled() const {
658+ return d_->canceled_;
659+ }
660+
661+ bool Gesture::ended() const {
662+ return d_->ended_;
663+ }
664+ }
665 }
666
667=== modified file 'src/v3/gesture.h'
668--- src/v3/gesture.h 2011-10-20 22:19:11 +0000
669+++ src/v3/gesture.h 2011-11-01 21:20:40 +0000
670@@ -31,49 +31,46 @@
671
672 #include "utouch/grail.h"
673
674-class Recognizer;
675-class UGSlice_;
676-
677-typedef std::shared_ptr<UGSlice_> SharedUGSlice_;
678-typedef std::set<unsigned int> TouchSet;
679-
680-class Gesture : public std::enable_shared_from_this<Gesture> {
681- public:
682- Gesture(Recognizer* recognizer, UGSubscription_* subscription,
683- TouchSet& touches, uint64_t start_time);
684- Gesture(const Gesture* gesture, TouchSet& touches);
685-
686- void Update(UFEvent event, TouchSet& touches);
687- bool IsOwned() const;
688- void FlushSlices();
689- uint64_t Timeout() const;
690- float AngleForTouch(unsigned int touch_id) const;
691- void SetAngleForTouch(unsigned int touch_id, float angle);
692- void Cancel();
693-
694- const unsigned int id() const { return id_; }
695- const Recognizer& recognizer() const { return *recognizer_; }
696- UGSubscription_* subscription() const { return subscription_; }
697- const TouchSet& touches() const { return touches_; }
698- const uint64_t start_time() const { return start_time_; }
699- bool canceled() const { return canceled_; }
700- bool ended() const { return ended_; }
701-
702- Gesture(const Gesture&) = delete;
703- void operator=(const Gesture&) = delete;
704-
705- private:
706- Recognizer* recognizer_;
707- unsigned int id_;
708- UGSubscription_* subscription_;
709- TouchSet touches_;
710- uint64_t start_time_;
711- UGGestureTypeMask recognized_;
712- std::queue<SharedUGSlice_> slices_;
713- SharedUGSlice_ last_slice_;
714- bool canceled_;
715- bool ended_;
716- std::map<unsigned int, float> angles_;
717-};
718-
719+namespace utouch {
720+ namespace grail {
721+ class Recognizer;
722+
723+ class UGSubscription;
724+ class UGSlice;
725+ typedef std::shared_ptr<UGSlice> SharedUGSlice;
726+
727+ typedef std::set<unsigned int> TouchSet;
728+
729+ class Gesture : public std::enable_shared_from_this<Gesture> {
730+ public:
731+ Gesture(Recognizer* recognizer, utouch::grail::UGSubscription* subscription,
732+ TouchSet& touches, uint64_t start_time);
733+ Gesture(const Gesture* gesture, TouchSet& touches);
734+
735+ void Update(UFEvent event, TouchSet& touches);
736+ bool IsOwned() const;
737+ void FlushSlices();
738+ uint64_t Timeout() const;
739+ float AngleForTouch(unsigned int touch_id) const;
740+ void SetAngleForTouch(unsigned int touch_id, float angle);
741+ void Cancel();
742+
743+ const unsigned int id() const;
744+ const Recognizer& recognizer() const;
745+ utouch::grail::UGSubscription* subscription() const;
746+ const TouchSet& touches() const;
747+ const uint64_t start_time() const;
748+ bool canceled() const;
749+ bool ended() const;
750+
751+ Gesture(const Gesture&) = delete;
752+ void operator=(const Gesture&) = delete;
753+
754+ private:
755+ struct Private;
756+ std::shared_ptr< Private > d_;
757+ };
758+
759+ }
760+}
761 #endif // UTOUCH_GRAIL_GESTURE_H_
762
763=== modified file 'src/v3/handle.cpp'
764--- src/v3/handle.cpp 2011-10-19 22:06:43 +0000
765+++ src/v3/handle.cpp 2011-11-01 21:20:40 +0000
766@@ -21,9 +21,9 @@
767
768 #include "v3/handle.h"
769
770-#include <assert.h>
771-#include <errno.h>
772-#include <stdio.h>
773+#include <cassert>
774+#include <cerrno>
775+#include <cstdio>
776 #include <sys/eventfd.h>
777 #include <unistd.h>
778
779@@ -33,315 +33,347 @@
780
781 #include "v3/event.h"
782 #include "v3/recognizer.h"
783+#include "v3/slice.h"
784 #include "v3/subscription.h"
785
786-UGHandle_::UGHandle_(UFHandle frame_handle)
787- : frame_handle_(frame_handle),
788- event_fd_(-1),
789- next_id_(0) {
790-}
791-
792-UGStatus UGHandle_::Initialize() {
793- event_fd_ = eventfd(0, EFD_NONBLOCK);
794- if (event_fd_ == -1) {
795- fprintf(stderr, "Error: failed to create eventfd instance\n");
796- return UGStatusErrorResources;
797- }
798-
799- return UGStatusSuccess;
800-}
801-
802-UGHandle_* UGHandle_::NewUGHandle_(UFHandle frame_handle) {
803- UGHandle_* handle = new UGHandle_(frame_handle);
804- if (handle->Initialize() != UGStatusSuccess) {
805- delete handle;
806- return NULL;
807- }
808-
809- return handle;
810-}
811-
812-UGStatus UGHandle_::ActivateSubscription(UGSubscription_* subscription) {
813- Recognizer* recognizer;
814-
815- if (!subscription->IsValid())
816- return UGStatusErrorInvalidSubscription;
817-
818- const auto& it =
819- recognizers_[subscription->device()].find(subscription->window());
820- if (it != recognizers_[subscription->device()].end()) {
821- recognizer = it->second.get();
822- } else {
823- recognizer = new Recognizer(this, subscription->device(),
824- subscription->window());
825- recognizers_[subscription->device()][subscription->window()] =
826- std::move(UniqueRecognizer(recognizer));
827- }
828-
829- recognizer->ActivateSubscription(subscription);
830-
831- return UGStatusSuccess;
832-}
833-
834-void UGHandle_::DeactivateSubscription(UGSubscription_* subscription) {
835- recognizers_[subscription->device()].erase(subscription->window());
836-}
837-
838-namespace {
839-
840-bool GetDeviceFromEvent(const UFEvent event, UFDevice* device) {
841- UFStatus status = frame_event_get_property(event, UFEventPropertyDevice,
842- device);
843- if (status != UFStatusSuccess) {
844- fprintf(stderr, "Warning: failed to get device from event\n");
845- return false;
846- }
847-
848- return true;
849-}
850-
851-bool GetDeviceAndWindowFromEvent(const UFEvent event, UFDevice* device,
852- Window* window) {
853- UFFrame frame;
854- UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
855- &frame);
856- if (status != UFStatusSuccess) {
857- fprintf(stderr, "Warning: failed to get frame from event\n");
858- return false;
859- }
860-
861- *device = frame_frame_get_device(frame);
862-
863- status = frame_frame_get_property(frame, UFFramePropertyWindow, window);
864- if (status != UFStatusSuccess) {
865- fprintf(stderr, "Warning: failed to get window from frame\n");
866- return false;
867- }
868-
869- return true;
870-}
871-
872-void RejectFrame(const UFEvent event, const UFDevice device, Window window) {
873- UFFrame frame;
874- UFStatus status;
875- unsigned int num_touches;
876- unsigned int i;
877-
878- status = frame_event_get_property(event, UFEventPropertyFrame, &frame);
879- if (status != UFStatusSuccess) {
880- fprintf(stderr, "Warning: failed to get frame from event\n");
881- return;
882- }
883-
884- num_touches = frame_frame_get_num_touches(frame);
885-
886- for (i = 0; i < num_touches; ++i) {
887- UFTouch touch;
888- unsigned int touch_id;
889-
890- status = frame_frame_get_touch_by_index(frame, i, &touch);
891- if (status != UFStatusSuccess) {
892- fprintf(stderr, "Warning: failed to get touch from frame by index\n");
893- continue;
894- }
895-
896- if (frame_touch_get_state(touch) != UFTouchStateBegin)
897- continue;
898-
899- status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
900- if (status != UFStatusSuccess) {
901- fprintf(stderr, "Warning: failed to get touch ID from touch\n");
902- continue;
903- }
904-
905- frame_x11_reject_touch(device, window, touch_id);
906- }
907-}
908-
909-} // namespace
910-
911-void UGHandle_::ProcessFrameEvent(const UFEvent event) {
912- switch (frame_event_get_type(event)) {
913- case UFEventTypeDeviceAdded: {
914- UFDevice device;
915- if (!GetDeviceFromEvent(event, &device))
916- return;
917- recognizers_.insert(std::make_pair(device,
918- std::map<Window, UniqueRecognizer>()));
919- break;
920- }
921-
922- case UFEventTypeDeviceRemoved: {
923- UFDevice device;
924- if (!GetDeviceFromEvent(event, &device))
925- return;
926- recognizers_.erase(device);
927- break;
928- }
929-
930- case UFEventTypeFrame: {
931- UFDevice device;
932- Window window;
933- if (!GetDeviceAndWindowFromEvent(event, &device, &window))
934- return;
935-
936- if (recognizers_[device].find(window) != recognizers_[device].end())
937- recognizers_[device][window]->ProcessFrameEvent(event);
938- else
939- RejectFrame(event, device, window);
940-
941- break;
942- }
943- }
944-}
945-
946-void UGHandle_::UpdateTime(uint64_t time) {
947- for (auto& pair : recognizers_)
948- for (auto& pair2 : pair.second)
949- pair2.second->UpdateTime(time);
950-}
951-
952-unsigned int UGHandle_::NewGestureID(Recognizer* recognizer) {
953- unsigned int id = next_id_++;
954- gestures_[id] = recognizer;
955- return id;
956-}
957-
958-void UGHandle_::EnqueueEvent(const UGEvent_* event) {
959- static const uint64_t num = 1;
960-
961- event_queue_.push_back(event);
962- if (write(event_fd_, &num, sizeof(num)) != sizeof(num))
963- fprintf(stderr, "Warning: failed to update eventfd instance\n");
964-}
965-
966-void UGHandle_::RemoveGestureFromEventQueue(unsigned int id) {
967- for (auto it = event_queue_.begin(); it != event_queue_.end(); ) {
968- const UGEvent_* event = *it++;
969- if (grail_event_get_type(event) != UGEventTypeSlice)
970- continue;
971-
972- UGSlice slice;
973- UGStatus status = grail_event_get_property(event, UGEventPropertySlice,
974- &slice);
975- assert(status == UGStatusSuccess);
976-
977- if (grail_slice_get_id(slice) == id) {
978- event_queue_.remove(event);
979- ReleaseEvent(event);
980- }
981- }
982-}
983-
984-UGStatus UGHandle_::GetEvent(const UGEvent_** event) {
985- /* Clear event fd (see eventfd(2) man page) */
986- uint64_t buf;
987- if (read(event_fd_, &buf, sizeof(buf)) != 8 && errno != EAGAIN)
988- fprintf(stderr, "Warning: failed to read data from event fd\n");
989-
990- if (event_queue_.empty())
991- return UGStatusErrorNoEvent;
992-
993- *event = event_queue_.front();
994- event_queue_.pop_front();
995-
996- return UGStatusSuccess;
997-}
998-
999-void UGHandle_::ReleaseEvent(const UGEvent_* event) {
1000- delete event;
1001-}
1002-
1003-uint64_t UGHandle_::NextTimeout() const {
1004- uint64_t min_timeout = std::numeric_limits<uint64_t>::max();
1005- for (auto& pair : recognizers_) {
1006- for (auto& pair2 : pair.second) {
1007- uint64_t timeout = pair2.second->NextTimeout();
1008- if (timeout < min_timeout)
1009- min_timeout = timeout;
1010- }
1011- }
1012-
1013- return min_timeout != std::numeric_limits<uint64_t>::max() ? min_timeout : 0;
1014-}
1015-
1016-UGStatus UGHandle_::AcceptGesture(unsigned int id) {
1017- auto it = gestures_.find(id);
1018- if (it == gestures_.end())
1019- return UGStatusErrorInvalidGesture;
1020-
1021- return it->second->AcceptGesture(id);
1022-}
1023-
1024-UGStatus UGHandle_::RejectGesture(unsigned int id) {
1025- auto it = gestures_.find(id);
1026- if (it == gestures_.end())
1027- return UGStatusErrorInvalidGesture;
1028-
1029- return it->second->RejectGesture(id);
1030-}
1031-
1032-UGHandle_::~UGHandle_() {
1033- while (!event_queue_.empty()) {
1034- ReleaseEvent(event_queue_.front());
1035- event_queue_.pop_front();
1036- }
1037-}
1038-
1039-extern "C" {
1040-
1041-UGStatus grail_new(UFHandle frame_handle, UGHandle* handle) {
1042- *handle = UGHandle_::NewUGHandle_(frame_handle);
1043- if (!*handle)
1044- return UGStatusErrorResources;
1045-
1046- return UGStatusSuccess;
1047-}
1048-
1049-void grail_delete_v3(UGHandle handle) {
1050- delete handle;
1051-}
1052-
1053-int grail_get_fd(UGHandle handle) {
1054- return handle->event_fd();
1055-}
1056-
1057-UGStatus grail_subscription_activate(UGHandle handle,
1058- const UGSubscription subscription) {
1059- return handle->ActivateSubscription(subscription);
1060-}
1061-
1062-void grail_subscription_deactivate(UGHandle handle,
1063- const UGSubscription subscription) {
1064- return handle->DeactivateSubscription(subscription);
1065-}
1066-
1067-void grail_process_frame_event(UGHandle handle, const UFEvent event) {
1068- handle->ProcessFrameEvent(event);
1069-}
1070-
1071-UGStatus grail_get_event(UGHandle handle, UGEvent *event) {
1072- return handle->GetEvent(event);
1073-}
1074-
1075-void grail_release_event(UGHandle handle, UGEvent event) {
1076- handle->ReleaseEvent(event);
1077-}
1078-
1079-void grail_update_time(UGHandle handle, uint64_t time) {
1080- handle->UpdateTime(time);
1081-}
1082-
1083-uint64_t grail_next_timeout(UGHandle handle) {
1084- return handle->NextTimeout();
1085-}
1086-
1087-UGStatus grail_accept_gesture(UGHandle handle, unsigned int id) {
1088- return handle->AcceptGesture(id);
1089-}
1090-
1091-UGStatus grail_reject_gesture(UGHandle handle, unsigned int id) {
1092- return handle->RejectGesture(id);
1093-}
1094-
1095-} // extern "C"
1096+namespace utouch {
1097+ namespace grail {
1098+
1099+ struct UGHandle::Private {
1100+
1101+ Private( UFHandle frame_handle )
1102+ : frame_handle_(frame_handle),
1103+ event_fd_(-1),
1104+ next_id_(0) {
1105+ }
1106+
1107+ typedef std::unique_ptr<Recognizer> UniqueRecognizer;
1108+
1109+ const UFHandle frame_handle_;
1110+ int event_fd_;
1111+ unsigned int next_id_;
1112+ std::map<UFDevice, std::map<Window, UniqueRecognizer>> recognizers_;
1113+ std::map<unsigned int, Recognizer*> gestures_;
1114+ std::list<utouch::grail::UGEvent*> event_queue_;
1115+
1116+ UGStatus Initialize() {
1117+ event_fd_ = eventfd(0, EFD_NONBLOCK);
1118+ if (event_fd_ == -1) {
1119+ fprintf(stderr, "Error: failed to create eventfd instance\n");
1120+ return UGStatusErrorResources;
1121+ }
1122+
1123+ return UGStatusSuccess;
1124+ }
1125+ };
1126+
1127+
1128+ UGHandle::UGHandle(UFHandle frame_handle)
1129+ : d_( new Private( frame_handle ) ) {
1130+ }
1131+
1132+ int UGHandle::event_fd() const {
1133+ return( d_->event_fd_ );
1134+ }
1135+
1136+ UGStatus UGHandle::ActivateSubscription( utouch::grail::UGSubscription * subscription) {
1137+ Recognizer* recognizer;
1138+
1139+ if (!subscription->IsValid())
1140+ return UGStatusErrorInvalidSubscription;
1141+
1142+ const auto& it =
1143+ d_->recognizers_[subscription->device()].find(subscription->window());
1144+ if (it != d_->recognizers_[subscription->device()].end()) {
1145+ recognizer = it->second.get();
1146+ } else {
1147+ recognizer = new Recognizer(this, subscription->device(),
1148+ subscription->window());
1149+ d_->recognizers_[subscription->device()][subscription->window()] =
1150+ std::move( Private::UniqueRecognizer( recognizer ) );
1151+ }
1152+
1153+ recognizer->ActivateSubscription( subscription );
1154+
1155+ return UGStatusSuccess;
1156+ }
1157+
1158+ void UGHandle::DeactivateSubscription( utouch::grail::UGSubscription * subscription) {
1159+ d_->recognizers_[subscription->device()].erase(subscription->window());
1160+ }
1161+
1162+ namespace {
1163+
1164+ bool GetDeviceFromEvent(const UFEvent event, UFDevice* device) {
1165+ UFStatus status = frame_event_get_property( event,
1166+ UFEventPropertyDevice,
1167+ device);
1168+ if (status != UFStatusSuccess) {
1169+ fprintf(stderr, "Warning: failed to get device from event\n");
1170+ return false;
1171+ }
1172+
1173+ return true;
1174+ }
1175+
1176+ bool GetDeviceAndWindowFromEvent(const UFEvent event, UFDevice* device,
1177+ Window* window) {
1178+ UFFrame frame;
1179+ UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
1180+ &frame);
1181+ if (status != UFStatusSuccess) {
1182+ fprintf(stderr, "Warning: failed to get frame from event\n");
1183+ return false;
1184+ }
1185+
1186+ *device = frame_frame_get_device(frame);
1187+
1188+ status = frame_frame_get_property(frame, UFFramePropertyWindow, window);
1189+ if (status != UFStatusSuccess) {
1190+ fprintf(stderr, "Warning: failed to get window from frame\n");
1191+ return false;
1192+ }
1193+
1194+ return true;
1195+ }
1196+
1197+ void RejectFrame(const UFEvent event, const UFDevice device, Window window) {
1198+ UFFrame frame;
1199+ UFStatus status;
1200+ unsigned int num_touches;
1201+ unsigned int i;
1202+
1203+ status = frame_event_get_property(event, UFEventPropertyFrame, &frame);
1204+ if (status != UFStatusSuccess) {
1205+ fprintf(stderr, "Warning: failed to get frame from event\n");
1206+ return;
1207+ }
1208+
1209+ num_touches = frame_frame_get_num_touches(frame);
1210+
1211+ for (i = 0; i < num_touches; ++i) {
1212+ UFTouch touch;
1213+ unsigned int touch_id;
1214+
1215+ status = frame_frame_get_touch_by_index(frame, i, &touch);
1216+ if (status != UFStatusSuccess) {
1217+ fprintf(stderr, "Warning: failed to get touch from frame by index\n");
1218+ continue;
1219+ }
1220+
1221+ if (frame_touch_get_state(touch) != UFTouchStateBegin)
1222+ continue;
1223+
1224+ status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
1225+ if (status != UFStatusSuccess) {
1226+ fprintf(stderr, "Warning: failed to get touch ID from touch\n");
1227+ continue;
1228+ }
1229+
1230+ frame_x11_reject_touch(device, window, touch_id);
1231+ }
1232+ }
1233+
1234+ } // namespace
1235+
1236+ void UGHandle::ProcessFrameEvent(const UFEvent event) {
1237+ switch (frame_event_get_type(event)) {
1238+ case UFEventTypeDeviceAdded: {
1239+ UFDevice device;
1240+ if (!GetDeviceFromEvent(event, &device))
1241+ return;
1242+ d_->recognizers_.insert(std::make_pair(device,
1243+ std::map<Window, Private::UniqueRecognizer>()));
1244+ break;
1245+ }
1246+
1247+ case UFEventTypeDeviceRemoved: {
1248+ UFDevice device;
1249+ if (!GetDeviceFromEvent(event, &device))
1250+ return;
1251+ d_->recognizers_.erase(device);
1252+ break;
1253+ }
1254+
1255+ case UFEventTypeFrame: {
1256+ UFDevice device;
1257+ Window window;
1258+ if (!GetDeviceAndWindowFromEvent(event, &device, &window))
1259+ return;
1260+
1261+ if (d_->recognizers_[device].find(window) != d_->recognizers_[device].end())
1262+ d_->recognizers_[device][window]->ProcessFrameEvent(event);
1263+ else
1264+ RejectFrame(event, device, window);
1265+
1266+ break;
1267+ }
1268+ }
1269+ }
1270+
1271+ void UGHandle::UpdateTime(uint64_t time) {
1272+ for (auto& pair : d_->recognizers_)
1273+ for (auto& pair2 : pair.second)
1274+ pair2.second->UpdateTime(time);
1275+ }
1276+
1277+ unsigned int UGHandle::NewGestureID(Recognizer* recognizer) {
1278+ unsigned int id = d_->next_id_++;
1279+ d_->gestures_[id] = recognizer;
1280+ return id;
1281+ }
1282+
1283+ void UGHandle::EnqueueEvent(utouch::grail::UGEvent * event) {
1284+ static const uint64_t num = 1;
1285+
1286+ d_->event_queue_.push_back(event);
1287+ if (write(d_->event_fd_, &num, sizeof(num)) != sizeof(num))
1288+ fprintf(stderr, "Warning: failed to update eventfd instance\n");
1289+ }
1290+
1291+ void UGHandle::RemoveGestureFromEventQueue(unsigned int id) {
1292+ for (auto it = d_->event_queue_.begin(); it != d_->event_queue_.end(); ) {
1293+ utouch::grail::UGEvent * event = *it++;
1294+ if (grail_event_get_type(event) != UGEventTypeSlice)
1295+ continue;
1296+
1297+ void * slice;
1298+ UGStatus status = grail_event_get_property( event,
1299+ UGEventPropertySlice,
1300+ &slice);
1301+ assert(status == UGStatusSuccess);
1302+
1303+ if (grail_slice_get_id(slice) == id) {
1304+ d_->event_queue_.remove(event);
1305+ ReleaseEvent(event);
1306+ }
1307+ }
1308+ }
1309+
1310+ UGStatus UGHandle::GetEvent( const utouch::grail::UGEvent ** event) {
1311+ /* Clear event fd (see eventfd(2) man page) */
1312+ uint64_t buf;
1313+ if( read(d_->event_fd_, &buf, sizeof(buf) ) != 8 && errno != EAGAIN)
1314+ fprintf(stderr, "Warning: failed to read data from event fd\n");
1315+
1316+ if (d_->event_queue_.empty())
1317+ return UGStatusErrorNoEvent;
1318+
1319+ *event = d_->event_queue_.front();
1320+ d_->event_queue_.pop_front();
1321+
1322+ return UGStatusSuccess;
1323+ }
1324+
1325+ void UGHandle::ReleaseEvent(const utouch::grail::UGEvent * event) {
1326+ delete event;
1327+ }
1328+
1329+ uint64_t UGHandle::NextTimeout() const {
1330+ uint64_t min_timeout = std::numeric_limits<uint64_t>::max();
1331+ for (auto& pair : d_->recognizers_) {
1332+ for (auto& pair2 : pair.second) {
1333+ uint64_t timeout = pair2.second->NextTimeout();
1334+ if (timeout < min_timeout)
1335+ min_timeout = timeout;
1336+ }
1337+ }
1338+
1339+ return min_timeout != std::numeric_limits<uint64_t>::max() ? min_timeout : 0;
1340+ }
1341+
1342+ UGStatus UGHandle::AcceptGesture(unsigned int id) {
1343+ auto it = d_->gestures_.find(id);
1344+ if (it == d_->gestures_.end())
1345+ return UGStatusErrorInvalidGesture;
1346+
1347+ return it->second->AcceptGesture(id);
1348+ }
1349+
1350+ UGStatus UGHandle::RejectGesture(unsigned int id) {
1351+ auto it = d_->gestures_.find(id);
1352+ if (it == d_->gestures_.end())
1353+ return UGStatusErrorInvalidGesture;
1354+
1355+ return it->second->RejectGesture(id);
1356+ }
1357+
1358+ UGHandle::~UGHandle() {
1359+ while (!d_->event_queue_.empty()) {
1360+ ReleaseEvent(d_->event_queue_.front());
1361+ d_->event_queue_.pop_front();
1362+ }
1363+ }
1364+ }
1365+
1366+ utouch::grail::UGHandle * utouch::grail::UGHandle::NewUGHandle( UFHandle frame_handle ) {
1367+ utouch::grail::UGHandle * handle = new utouch::grail::UGHandle(frame_handle);
1368+ if( handle->d_->Initialize() != UGStatusSuccess ) {
1369+ delete handle;
1370+ return NULL;
1371+ }
1372+
1373+ return handle;
1374+ }
1375+
1376+ UGStatus grail_new(UFHandle frame_handle, UGHandle* handle) {
1377+ assert( handle == NULL );
1378+ *handle = utouch::grail::UGHandle::NewUGHandle(frame_handle);
1379+ if (!*handle)
1380+ return UGStatusErrorResources;
1381+
1382+ return UGStatusSuccess;
1383+ }
1384+
1385+ void grail_delete_v3(UGHandle handle) {
1386+ assert( handle == NULL );
1387+ delete( static_cast< utouch::grail::UGHandle* >( handle ) );
1388+ }
1389+
1390+ int grail_get_fd(UGHandle handle) {
1391+ assert( handle == NULL );
1392+ return static_cast< utouch::grail::UGHandle* >( handle )->event_fd();
1393+ }
1394+
1395+ UGStatus grail_subscription_activate(UGHandle handle,
1396+ const UGSubscription subscription) {
1397+ assert( handle == NULL );
1398+ return static_cast< utouch::grail::UGHandle* >( handle )->ActivateSubscription(static_cast< utouch::grail::UGSubscription* >( subscription ) );
1399+ }
1400+
1401+ void grail_subscription_deactivate(UGHandle handle,
1402+ const UGSubscription subscription) {
1403+ assert( handle == NULL );
1404+ return static_cast< utouch::grail::UGHandle* >( handle )->DeactivateSubscription( static_cast< utouch::grail::UGSubscription* >( subscription ) );
1405+ }
1406+
1407+ void grail_process_frame_event(UGHandle handle, const UFEvent event) {
1408+ assert( handle == NULL );
1409+ static_cast< utouch::grail::UGHandle* >( handle )->ProcessFrameEvent( event );
1410+ }
1411+
1412+ UGStatus grail_get_event(UGHandle handle, UGEvent *event) {
1413+ const utouch::grail::UGEvent * uge = static_cast< const utouch::grail::UGEvent* >( *event );
1414+ return static_cast< utouch::grail::UGHandle* >( handle )->GetEvent( &uge );
1415+ }
1416+
1417+ void grail_release_event(UGHandle handle, UGEvent event) {
1418+ static_cast< utouch::grail::UGHandle* >( handle )->ReleaseEvent( static_cast< const utouch::grail::UGEvent* >( event ) );
1419+ }
1420+
1421+ void grail_update_time(UGHandle handle, uint64_t time) {
1422+ static_cast< utouch::grail::UGHandle* >( handle )->UpdateTime(time);
1423+ }
1424+
1425+ uint64_t grail_next_timeout(UGHandle handle) {
1426+ return static_cast< utouch::grail::UGHandle* >( handle )->NextTimeout();
1427+ }
1428+
1429+ UGStatus grail_accept_gesture(UGHandle handle, unsigned int id) {
1430+ return static_cast< utouch::grail::UGHandle* >( handle )->AcceptGesture(id);
1431+ }
1432+
1433+ UGStatus grail_reject_gesture(UGHandle handle, unsigned int id) {
1434+ return static_cast< utouch::grail::UGHandle* >( handle )->RejectGesture(id);
1435+ }
1436+}
1437
1438=== modified file 'src/v3/handle.h'
1439--- src/v3/handle.h 2011-10-18 21:35:48 +0000
1440+++ src/v3/handle.h 2011-11-01 21:20:40 +0000
1441@@ -31,44 +31,43 @@
1442
1443 #include "utouch/grail.h"
1444
1445-class Recognizer;
1446-class UGEvent_;
1447-
1448-class UGHandle_ {
1449- public:
1450- static UGHandle_* NewUGHandle_(UFHandle frame_handle);
1451-
1452- ~UGHandle_();
1453-
1454- int event_fd() const { return event_fd_; }
1455- UGStatus ActivateSubscription(UGSubscription_* subscription);
1456- void DeactivateSubscription(UGSubscription_* subscription);
1457- unsigned int NewGestureID(Recognizer* recognizer);
1458- void ProcessFrameEvent(UFEvent event);
1459- void UpdateTime(uint64_t time);
1460- uint64_t NextTimeout() const;
1461- void EnqueueEvent(const UGEvent_*);
1462- void RemoveGestureFromEventQueue(unsigned int id);
1463- UGStatus GetEvent(const UGEvent_** event);
1464- void ReleaseEvent(const UGEvent_* event);
1465- UGStatus AcceptGesture(unsigned int id);
1466- UGStatus RejectGesture(unsigned int id);
1467-
1468- UGHandle_(const UGHandle_&) = delete;
1469- void operator=(const UGHandle_&) = delete;
1470-
1471- private:
1472- typedef std::unique_ptr<Recognizer> UniqueRecognizer;
1473-
1474- const UFHandle frame_handle_;
1475- int event_fd_;
1476- unsigned int next_id_;
1477- std::map<UFDevice, std::map<Window, UniqueRecognizer>> recognizers_;
1478- std::map<unsigned int, Recognizer*> gestures_;
1479- std::list<const UGEvent_*> event_queue_;
1480-
1481- UGHandle_(UFHandle frame_handle);
1482- UGStatus Initialize();
1483-};
1484-
1485+namespace utouch {
1486+ namespace grail {
1487+
1488+ class Recognizer;
1489+
1490+ class UGEvent;
1491+ class UGSubscription;
1492+
1493+ class UGHandle {
1494+ public:
1495+ static UGHandle* NewUGHandle(UFHandle frame_handle);
1496+
1497+ ~UGHandle();
1498+
1499+ int event_fd() const;
1500+ UGStatus ActivateSubscription( utouch::grail::UGSubscription* subscription);
1501+ void DeactivateSubscription( utouch::grail::UGSubscription* subscription);
1502+ unsigned int NewGestureID(Recognizer* recognizer);
1503+ void ProcessFrameEvent(UFEvent event);
1504+ void UpdateTime(uint64_t time);
1505+ uint64_t NextTimeout() const;
1506+ void EnqueueEvent(utouch::grail::UGEvent * );
1507+ void RemoveGestureFromEventQueue(unsigned int id);
1508+ UGStatus GetEvent( const utouch::grail::UGEvent ** event );
1509+ void ReleaseEvent(const utouch::grail::UGEvent * event);
1510+ UGStatus AcceptGesture(unsigned int id);
1511+ UGStatus RejectGesture(unsigned int id);
1512+
1513+ UGHandle(const UGHandle&) = delete;
1514+ void operator=(const UGHandle&) = delete;
1515+
1516+ protected:
1517+ struct Private;
1518+ std::shared_ptr< Private > d_;
1519+
1520+ UGHandle(UFHandle frame_handle);
1521+ };
1522+ }
1523+}
1524 #endif // UTOUCH_GRAIL_HANDLE_H_
1525
1526=== modified file 'src/v3/recognizer.cpp'
1527--- src/v3/recognizer.cpp 2011-10-19 22:07:30 +0000
1528+++ src/v3/recognizer.cpp 2011-11-01 21:20:40 +0000
1529@@ -21,8 +21,8 @@
1530
1531 #include "v3/recognizer.h"
1532
1533-#include <stdint.h>
1534-#include <stdio.h>
1535+#include <cstdint>
1536+#include <cstdio>
1537
1538 #include <algorithm>
1539 #include <limits>
1540@@ -35,492 +35,541 @@
1541
1542 namespace {
1543
1544-const uint64_t kCompositionTime = 60;
1545-
1546-} // namespace
1547-
1548-Recognizer::Recognizer(UGHandle_* handle, const UFDevice device, Window window)
1549- : handle_(handle),
1550- device_(device),
1551- window_(window),
1552- device_x_res_(46), /* Default to resolution of Apple Magic Trackpad */
1553- device_y_res_(45),
1554- device_direct_(true) {
1555- UFAxis axis;
1556- UFStatus status = frame_device_get_axis_by_type(device, UFAxisTypeX, &axis);
1557- if (status != UFStatusSuccess)
1558- fprintf(stderr, "Warning: failed to get X axis from device\n");
1559- else
1560- device_x_res_ = frame_axis_get_resolution(axis);
1561-
1562- status = frame_device_get_axis_by_type(device, UFAxisTypeY, &axis);
1563- if (status != UFStatusSuccess)
1564- fprintf(stderr, "Warning: failed to get Y axis from device\n");
1565- else
1566- device_y_res_ = frame_axis_get_resolution(axis);
1567-
1568- status = frame_device_get_property(device, UFDevicePropertyDirect,
1569- &device_direct_);
1570- if (status != UFStatusSuccess)
1571- fprintf(stderr,
1572- "Warning: failed to get direct property value for device\n");
1573-}
1574-
1575-void Recognizer::ActivateSubscription(UGSubscription_* subscription) {
1576- subscriptions_[subscription->touches_start() - 1].insert(subscription);
1577-}
1578-
1579-void Recognizer::DeactivateSubscription(UGSubscription_* subscription) {
1580- subscriptions_[subscription->touches_start() - 1].erase(subscription);
1581-
1582- for (auto it = unaccepted_gestures_.begin();
1583- it != unaccepted_gestures_.end();
1584- ) {
1585- const SharedGesture& gesture = *it++;
1586- if (gesture->subscription() == subscription)
1587- gesture->Cancel();
1588- unaccepted_gestures_.erase(gesture);
1589- }
1590-
1591- for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) {
1592- const SharedGesture& gesture = *it++;
1593- if (gesture->subscription() == subscription)
1594- gesture->Cancel();
1595- accepted_gestures_.erase(gesture);
1596- }
1597-}
1598-
1599-void Recognizer::ProcessFrameEvent(const UFEvent event) {
1600- UpdateTime(frame_event_get_time(event));
1601- MatchSubscriptionsForEvent(event);
1602- ProcessEvent(event);
1603-}
1604-
1605-void Recognizer::MatchSubscriptionsForEvent(const UFEvent event) {
1606- bool active_subscriptions = false;
1607- for (auto subscriptions : subscriptions_) {
1608- if (!subscriptions.empty()) {
1609- active_subscriptions = true;
1610- break;
1611- }
1612- }
1613- if (!active_subscriptions)
1614- return;
1615-
1616- UFFrame frame;
1617- UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
1618- &frame);
1619- if (status != UFStatusSuccess) {
1620- fprintf(stderr, "Warning: failed to get frame from event\n");
1621- return;
1622- }
1623-
1624- unsigned int num_touches = frame_frame_get_num_touches(frame);
1625- for (unsigned int i = 0; i < num_touches; ++i) {
1626- UFTouch touch;
1627- status = frame_frame_get_touch_by_index(frame, i, &touch);
1628- if (status != UFStatusSuccess) {
1629- fprintf(stderr, "Warning: failed to get touch from frame\n");
1630- continue;
1631- }
1632-
1633- unsigned int touch_id;
1634- status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
1635- if (status != UFStatusSuccess) {
1636- fprintf(stderr, "Warning: failed to get touch id from touch\n");
1637- continue;
1638- }
1639-
1640- switch (frame_touch_get_state(touch)) {
1641- case UFTouchStateBegin: {
1642- start_times_[touch_id] = frame_touch_get_start_time(touch);
1643- unaccepted_touches_.insert(touch_id);
1644- free_touches_.insert(touch_id);
1645-
1646- for (const SharedGesture& gesture : accepted_gestures_) {
1647- UGSubscription_* subscription = gesture->subscription();
1648- if (gesture->touches().size() < subscription->touches_max()) {
1649- TouchSet set(gesture->touches());
1650- set.insert(touch_id);
1651- Gesture* new_gesture = new Gesture(gesture.get(), set);
1652- unaccepted_gestures_.insert(SharedGesture(new_gesture));
1653- }
1654- }
1655-
1656- for (const SharedGesture& gesture : unaccepted_gestures_) {
1657- UGSubscription_* subscription = gesture->subscription();
1658- if (gesture->touches().size() < subscription->touches_max()) {
1659- TouchSet set(gesture->touches());
1660- set.insert(touch_id);
1661- Gesture* new_gesture = new Gesture(gesture.get(), set);
1662- unaccepted_gestures_.insert(SharedGesture(new_gesture));
1663- }
1664- }
1665-
1666- MatchOneTouchGestures(touch_id);
1667- MatchTwoTouchGestures(touch_id);
1668- MatchThreeTouchGestures(touch_id);
1669- MatchFourTouchGestures(touch_id);
1670- MatchFiveTouchGestures(touch_id);
1671- break;
1672- }
1673-
1674- default:
1675- break;
1676- }
1677- }
1678-}
1679-
1680-void Recognizer::MatchOneTouchGestures(unsigned int touch_id) {
1681- for (UGSubscription_* subscription : subscriptions_[0]) {
1682- TouchSet set;
1683- set.insert(touch_id);
1684- Gesture* gesture = new Gesture(this, subscription, set,
1685- start_times_[touch_id]);
1686- unaccepted_gestures_.insert(SharedGesture(gesture));
1687- }
1688-}
1689-
1690-void Recognizer::MatchTwoTouchGestures(unsigned int touch_id) {
1691- for (UGSubscription_* subscription : subscriptions_[1]) {
1692- for (unsigned int other_id : free_touches_) {
1693- if (other_id == touch_id)
1694- continue;
1695-
1696- uint64_t min_start_time = start_times_[touch_id];
1697- if (start_times_[other_id] < min_start_time &&
1698- unaccepted_touches_.find(other_id) != unaccepted_touches_.end())
1699- min_start_time = start_times_[other_id];
1700-
1701- if (start_times_[touch_id] - min_start_time < kCompositionTime) {
1702- TouchSet set;
1703- set.insert(touch_id);
1704- set.insert(other_id);
1705- Gesture* gesture = new Gesture(this, subscription, set,
1706- start_times_[touch_id]);
1707- unaccepted_gestures_.insert(SharedGesture(gesture));
1708- }
1709- }
1710- }
1711-}
1712-
1713-void Recognizer::MatchThreeTouchGestures(unsigned int touch_id) {
1714- for (UGSubscription_* subscription : subscriptions_[2]) {
1715- for (unsigned int other_id_1 : free_touches_) {
1716- if (other_id_1 == touch_id)
1717- continue;
1718-
1719- for (unsigned int other_id_2 : free_touches_) {
1720- if (other_id_2 == touch_id || other_id_2 == other_id_1)
1721- continue;
1722-
1723- uint64_t min_start_time = start_times_[touch_id];
1724- if (start_times_[other_id_1] < min_start_time &&
1725- unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end())
1726- min_start_time = start_times_[other_id_1];
1727- if (start_times_[other_id_2] < min_start_time &&
1728- unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end())
1729- min_start_time = start_times_[other_id_2];
1730-
1731- if (start_times_[touch_id] - min_start_time < kCompositionTime) {
1732- TouchSet set;
1733- set.insert(touch_id);
1734- set.insert(other_id_1);
1735- set.insert(other_id_2);
1736- Gesture* gesture = new Gesture(this, subscription, set,
1737- start_times_[touch_id]);
1738- unaccepted_gestures_.insert(SharedGesture(gesture));
1739- }
1740- }
1741- }
1742- }
1743-}
1744-
1745-void Recognizer::MatchFourTouchGestures(unsigned int touch_id) {
1746- for (UGSubscription_* subscription : subscriptions_[3]) {
1747- for (unsigned int other_id_1 : free_touches_) {
1748- if (other_id_1 == touch_id)
1749- continue;
1750-
1751- for (unsigned int other_id_2 : free_touches_) {
1752- if (other_id_2 == touch_id || other_id_2 == other_id_1)
1753- continue;
1754-
1755- for (unsigned int other_id_3 : free_touches_) {
1756- if (other_id_3 == touch_id || other_id_3 == other_id_1 ||
1757- other_id_3 == other_id_2)
1758- continue;
1759-
1760- uint64_t min_start_time = start_times_[touch_id];
1761- if (start_times_[other_id_1] < min_start_time &&
1762- unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end())
1763- min_start_time = start_times_[other_id_1];
1764- if (start_times_[other_id_2] < min_start_time &&
1765- unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end())
1766- min_start_time = start_times_[other_id_2];
1767- if (start_times_[other_id_3] < min_start_time &&
1768- unaccepted_touches_.find(other_id_3) != unaccepted_touches_.end())
1769- min_start_time = start_times_[other_id_3];
1770-
1771- if (start_times_[touch_id] - min_start_time < kCompositionTime) {
1772- TouchSet set;
1773- set.insert(touch_id);
1774- set.insert(other_id_1);
1775- set.insert(other_id_2);
1776- set.insert(other_id_3);
1777- Gesture* gesture = new Gesture(this, subscription, set,
1778- start_times_[touch_id]);
1779- unaccepted_gestures_.insert(SharedGesture(gesture));
1780- }
1781- }
1782- }
1783- }
1784- }
1785-}
1786-
1787-void Recognizer::MatchFiveTouchGestures(unsigned int touch_id) {
1788- for (UGSubscription_* subscription : subscriptions_[4]) {
1789- for (unsigned int other_id_1 : free_touches_) {
1790- if (other_id_1 == touch_id)
1791- continue;
1792-
1793- for (unsigned int other_id_2 : free_touches_) {
1794- if (other_id_2 == touch_id || other_id_2 == other_id_1)
1795- continue;
1796-
1797- for (unsigned int other_id_3 : free_touches_) {
1798- if (other_id_3 == touch_id || other_id_3 == other_id_1 ||
1799- other_id_3 == other_id_2)
1800- continue;
1801-
1802- for (unsigned int other_id_4 : free_touches_) {
1803- if (other_id_4 == touch_id || other_id_4 == other_id_1 ||
1804- other_id_4 == other_id_2 || other_id_4 == other_id_3)
1805- continue;
1806-
1807- uint64_t min_start_time = start_times_[touch_id];
1808- if (start_times_[other_id_1] < min_start_time &&
1809- unaccepted_touches_.find(other_id_1) !=
1810- unaccepted_touches_.end())
1811- min_start_time = start_times_[other_id_1];
1812- if (start_times_[other_id_2] < min_start_time &&
1813- unaccepted_touches_.find(other_id_2) !=
1814- unaccepted_touches_.end())
1815- min_start_time = start_times_[other_id_2];
1816- if (start_times_[other_id_3] < min_start_time &&
1817- unaccepted_touches_.find(other_id_3) !=
1818- unaccepted_touches_.end())
1819- min_start_time = start_times_[other_id_3];
1820- if (start_times_[other_id_4] < min_start_time &&
1821- unaccepted_touches_.find(other_id_4) !=
1822- unaccepted_touches_.end())
1823- min_start_time = start_times_[other_id_4];
1824-
1825- if (start_times_[touch_id] - min_start_time < kCompositionTime) {
1826- TouchSet set;
1827- set.insert(touch_id);
1828- set.insert(other_id_1);
1829- set.insert(other_id_2);
1830- set.insert(other_id_3);
1831- set.insert(other_id_4);
1832- Gesture* gesture = new Gesture(this, subscription, set,
1833- start_times_[touch_id]);
1834- unaccepted_gestures_.insert(SharedGesture(gesture));
1835- }
1836- }
1837- }
1838- }
1839- }
1840- }
1841-}
1842-
1843-namespace {
1844-
1845-void GetModifiedAndEndedTouches(UFFrame frame, TouchSet* modified,
1846- TouchSet* ended, uint64_t event_time) {
1847- unsigned int num_touches = frame_frame_get_num_touches(frame);
1848- for (unsigned int i = 0; i < num_touches; ++i) {
1849- UFTouch touch;
1850- UFStatus status = frame_frame_get_touch_by_index(frame, i, &touch);
1851- if (status != UFStatusSuccess) {
1852- fprintf(stderr, "Warning: failed to get touch from frame\n");
1853- continue;
1854- }
1855-
1856- if (frame_touch_get_time(touch) == event_time) {
1857- unsigned int touch_id;
1858- status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
1859- if (status != UFStatusSuccess) {
1860- fprintf(stderr, "Warning: failed to get touch id from touch\n");
1861- continue;
1862- }
1863-
1864- modified->insert(touch_id);
1865-
1866- if (frame_touch_get_state(touch) == UFTouchStateEnd)
1867- ended->insert(touch_id);
1868- }
1869- }
1870-}
1871-
1872-} // namespace
1873-
1874-void Recognizer::ProcessEvent(const UFEvent& event) {
1875- UFFrame frame;
1876- UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
1877- &frame);
1878- if (status != UFStatusSuccess) {
1879- fprintf(stderr, "Warning: failed to get frame from event\n");
1880- return;
1881- }
1882-
1883- TouchSet modified_touches;
1884- TouchSet ended_touches;
1885- GetModifiedAndEndedTouches(frame, &modified_touches,
1886- &ended_touches, frame_event_get_time(event));
1887-
1888- for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) {
1889- const SharedGesture& gesture = *it++;
1890- gesture->Update(event, modified_touches);
1891- if (gesture->ended()) {
1892- for (unsigned int touch_id : gesture->touches())
1893- free_touches_.insert(touch_id);
1894- accepted_gestures_.erase(gesture);
1895- }
1896- }
1897-
1898- for (auto it = unaccepted_gestures_.begin();
1899- it != unaccepted_gestures_.end();
1900- ) {
1901- const SharedGesture& gesture = *it++;
1902- gesture->Update(event, modified_touches);
1903- if (gesture->canceled())
1904- RejectGesture(gesture);
1905- }
1906-
1907- for (unsigned int touch_id : ended_touches)
1908- free_touches_.erase(touch_id);
1909-}
1910-
1911-void Recognizer::UpdateTime(uint64_t time) {
1912- for (auto it = unaccepted_gestures_.begin();
1913- it != unaccepted_gestures_.end();
1914- ) {
1915- const SharedGesture& gesture = *it++;
1916- uint64_t timeout = gesture->Timeout();
1917- if (timeout && time - gesture->start_time() > timeout)
1918- RejectGesture(gesture);
1919- }
1920-
1921- for (auto it = unaccepted_touches_.begin(); it
1922- != unaccepted_touches_.end();
1923- ) {
1924- unsigned int touch_id = *it++;
1925- if (time - start_times_[touch_id] < kCompositionTime)
1926- continue;
1927-
1928- for (const SharedGesture& gesture : unaccepted_gestures_)
1929- if (gesture->touches().find(touch_id) != gesture->touches().end())
1930- goto next_touch;
1931-
1932- frame_x11_reject_touch(device_, window_, touch_id);
1933- unaccepted_touches_.erase(touch_id);
1934- free_touches_.erase(touch_id);
1935-
1936-next_touch: ;
1937- }
1938-}
1939-
1940-uint64_t Recognizer::NextTimeout() {
1941- uint64_t min_timeout = std::numeric_limits<uint64_t>::max();
1942- for (unsigned int touch_id : unaccepted_touches_)
1943- if (kCompositionTime + start_times_[touch_id] < min_timeout)
1944- min_timeout = start_times_[touch_id] + kCompositionTime;
1945-
1946- for (const SharedGesture& gesture : unaccepted_gestures_) {
1947- uint64_t timeout = gesture->Timeout();
1948- if (timeout && gesture->start_time() + timeout < min_timeout)
1949- min_timeout = gesture->start_time() + timeout;
1950- }
1951-
1952- return min_timeout;
1953-}
1954-
1955-UGStatus Recognizer::AcceptGesture(unsigned int id) {
1956- SharedGesture gesture;
1957- for (const SharedGesture& test_gesture : unaccepted_gestures_) {
1958- if (test_gesture->id() == id) {
1959- gesture = test_gesture;
1960- break;
1961- }
1962- }
1963-
1964- if (!gesture)
1965- return UGStatusErrorInvalidGesture;
1966-
1967- for (unsigned int touch_id : gesture->touches()) {
1968- if (accepted_touches_.find(touch_id) == accepted_touches_.end()) {
1969- frame_x11_accept_touch(device_, window_, touch_id);
1970- accepted_touches_.insert(touch_id);
1971- unaccepted_touches_.erase(touch_id);
1972- } else {
1973- for (auto it = accepted_gestures_.begin();
1974- it != accepted_gestures_.end();
1975- ) {
1976- const SharedGesture& other_gesture = *it++;
1977- const TouchSet& other_touches = other_gesture->touches();
1978- if (other_touches.find(touch_id) != other_touches.end()) {
1979- gesture->Cancel();
1980- handle_->RemoveGestureFromEventQueue(other_gesture->id());
1981- accepted_gestures_.erase(other_gesture);
1982- }
1983- }
1984- }
1985-
1986- free_touches_.erase(touch_id);
1987- }
1988-
1989- for (auto it = unaccepted_gestures_.begin();
1990- it != unaccepted_gestures_.end();
1991- ) {
1992- const SharedGesture& other_gesture = *it++;
1993- if (other_gesture == gesture)
1994- continue;
1995- for (unsigned int touch_id : other_gesture->touches()) {
1996- if (gesture->touches().find(touch_id) != gesture->touches().end()) {
1997- RejectGesture(other_gesture);
1998- break;
1999- }
2000- }
2001- }
2002-
2003- accepted_gestures_.insert(gesture);
2004- unaccepted_gestures_.erase(gesture);
2005-
2006- return UGStatusSuccess;
2007-}
2008-
2009-UGStatus Recognizer::RejectGesture(unsigned int id) {
2010- for (const SharedGesture& gesture : unaccepted_gestures_) {
2011- if (gesture->id() == id) {
2012- RejectGesture(gesture);
2013- return UGStatusSuccess;
2014- }
2015- }
2016-
2017- return UGStatusErrorInvalidGesture;
2018-}
2019-
2020-void Recognizer::RejectGesture(const SharedGesture& gesture) {
2021- gesture->Cancel();
2022- handle_->RemoveGestureFromEventQueue(gesture->id());
2023- unaccepted_gestures_.erase(gesture);
2024-}
2025-
2026-Recognizer::~Recognizer() {
2027- for (const SharedGesture& gesture : unaccepted_gestures_)
2028- gesture->Cancel();
2029-
2030- for (const SharedGesture& gesture : accepted_gestures_)
2031- gesture->Cancel();
2032+ const uint64_t kCompositionTime = 60;
2033+
2034+ void GetModifiedAndEndedTouches(UFFrame frame, utouch::grail::TouchSet* modified,
2035+ utouch::grail::TouchSet* ended, uint64_t event_time) {
2036+ unsigned int num_touches = frame_frame_get_num_touches(frame);
2037+ for (unsigned int i = 0; i < num_touches; ++i) {
2038+ UFTouch touch;
2039+ UFStatus status = frame_frame_get_touch_by_index(frame, i, &touch);
2040+ if (status != UFStatusSuccess) {
2041+ fprintf(stderr, "Warning: failed to get touch from frame\n");
2042+ continue;
2043+ }
2044+
2045+ if (frame_touch_get_time(touch) == event_time) {
2046+ unsigned int touch_id;
2047+ status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
2048+ if (status != UFStatusSuccess) {
2049+ fprintf(stderr, "Warning: failed to get touch id from touch\n");
2050+ continue;
2051+ }
2052+
2053+ modified->insert(touch_id);
2054+
2055+ if (frame_touch_get_state(touch) == UFTouchStateEnd)
2056+ ended->insert(touch_id);
2057+ }
2058+ }
2059+ }
2060+
2061+} // namespace
2062+
2063+namespace utouch {
2064+ namespace grail {
2065+
2066+ struct Recognizer::Private {
2067+
2068+ Private( Recognizer * parent, utouch::grail::UGHandle * handle, const UFDevice device, Window window)
2069+ : parent_( parent ),
2070+ handle_(handle),
2071+ device_(device),
2072+ window_(window),
2073+ device_x_res_(46), /* Default to resolution of Apple Magic Trackpad */
2074+ device_y_res_(45),
2075+ device_direct_(true) {
2076+ UFAxis axis;
2077+ UFStatus status = frame_device_get_axis_by_type(device, UFAxisTypeX, &axis);
2078+ if (status != UFStatusSuccess)
2079+ fprintf(stderr, "Warning: failed to get X axis from device\n");
2080+ else
2081+ device_x_res_ = frame_axis_get_resolution(axis);
2082+
2083+ status = frame_device_get_axis_by_type(device, UFAxisTypeY, &axis);
2084+ if (status != UFStatusSuccess)
2085+ fprintf(stderr, "Warning: failed to get Y axis from device\n");
2086+ else
2087+ device_y_res_ = frame_axis_get_resolution(axis);
2088+
2089+ status = frame_device_get_property( device,
2090+ UFDevicePropertyDirect,
2091+ &device_direct_);
2092+ if (status != UFStatusSuccess)
2093+ fprintf(stderr,
2094+ "Warning: failed to get direct property value for device\n");
2095+ }
2096+
2097+ void MatchSubscriptionsForEvent(const UFEvent event) {
2098+ bool active_subscriptions = false;
2099+ for (auto subscriptions : subscriptions_) {
2100+ if (!subscriptions.empty()) {
2101+ active_subscriptions = true;
2102+ break;
2103+ }
2104+ }
2105+ if (!active_subscriptions)
2106+ return;
2107+
2108+ UFFrame frame;
2109+ UFStatus status = frame_event_get_property( event,
2110+ UFEventPropertyFrame,
2111+ &frame);
2112+ if (status != UFStatusSuccess) {
2113+ fprintf(stderr, "Warning: failed to get frame from event\n");
2114+ return;
2115+ }
2116+
2117+ unsigned int num_touches = frame_frame_get_num_touches(frame);
2118+ for (unsigned int i = 0; i < num_touches; ++i) {
2119+ UFTouch touch;
2120+ status = frame_frame_get_touch_by_index(frame, i, &touch);
2121+ if (status != UFStatusSuccess) {
2122+ fprintf(stderr, "Warning: failed to get touch from frame\n");
2123+ continue;
2124+ }
2125+
2126+ unsigned int touch_id;
2127+ status = frame_touch_get_property(touch, UFTouchPropertyId, &touch_id);
2128+ if (status != UFStatusSuccess) {
2129+ fprintf(stderr, "Warning: failed to get touch id from touch\n");
2130+ continue;
2131+ }
2132+
2133+ switch (frame_touch_get_state(touch)) {
2134+ case UFTouchStateBegin: {
2135+ start_times_[touch_id] = frame_touch_get_start_time(touch);
2136+ unaccepted_touches_.insert(touch_id);
2137+ free_touches_.insert(touch_id);
2138+
2139+ for (const utouch::grail::SharedGesture & gesture : accepted_gestures_) {
2140+ utouch::grail::UGSubscription * subscription = gesture->subscription();
2141+ if (gesture->touches().size() < subscription->touches_max()) {
2142+ TouchSet set(gesture->touches());
2143+ set.insert(touch_id);
2144+ utouch::grail::Gesture* new_gesture = new utouch::grail::Gesture(gesture.get(), set);
2145+ unaccepted_gestures_.insert(utouch::grail::SharedGesture(new_gesture));
2146+ }
2147+ }
2148+
2149+ for (const utouch::grail::SharedGesture & gesture : unaccepted_gestures_) {
2150+ utouch::grail::UGSubscription* subscription = gesture->subscription();
2151+ if (gesture->touches().size() < subscription->touches_max()) {
2152+ TouchSet set(gesture->touches());
2153+ set.insert(touch_id);
2154+ utouch::grail::Gesture * new_gesture = new utouch::grail::Gesture(gesture.get(), set);
2155+ unaccepted_gestures_.insert( utouch::grail::SharedGesture(new_gesture));
2156+ }
2157+ }
2158+
2159+ MatchOneTouchGestures(touch_id);
2160+ MatchTwoTouchGestures(touch_id);
2161+ MatchThreeTouchGestures(touch_id);
2162+ MatchFourTouchGestures(touch_id);
2163+ MatchFiveTouchGestures(touch_id);
2164+ break;
2165+ }
2166+
2167+ default:
2168+ break;
2169+ }
2170+ }
2171+ }
2172+
2173+ void MatchOneTouchGestures(unsigned int touch_id) {
2174+ for( utouch::grail::UGSubscription* subscription : subscriptions_[0] ) {
2175+ TouchSet set;
2176+ set.insert(touch_id);
2177+ utouch::grail::Gesture* gesture = new utouch::grail::Gesture( parent_,
2178+ subscription, set,
2179+ start_times_[touch_id]);
2180+ unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture));
2181+ }
2182+ }
2183+
2184+ void MatchTwoTouchGestures(unsigned int touch_id) {
2185+ for( utouch::grail::UGSubscription* subscription : subscriptions_[1] ) {
2186+ for (unsigned int other_id : free_touches_) {
2187+ if (other_id == touch_id)
2188+ continue;
2189+
2190+ uint64_t min_start_time = start_times_[touch_id];
2191+ if (start_times_[other_id] < min_start_time &&
2192+ unaccepted_touches_.find(other_id) != unaccepted_touches_.end())
2193+ min_start_time = start_times_[other_id];
2194+
2195+ if (start_times_[touch_id] - min_start_time < kCompositionTime) {
2196+ TouchSet set;
2197+ set.insert(touch_id);
2198+ set.insert(other_id);
2199+ utouch::grail::Gesture* gesture = new utouch::grail::Gesture(parent_, subscription, set,
2200+ start_times_[touch_id]);
2201+ unaccepted_gestures_.insert( utouch::grail::SharedGesture(gesture) );
2202+ }
2203+ }
2204+ }
2205+ }
2206+
2207+ void MatchThreeTouchGestures(unsigned int touch_id) {
2208+ for( utouch::grail::UGSubscription* subscription : subscriptions_[2] ) {
2209+ for (unsigned int other_id_1 : free_touches_) {
2210+ if (other_id_1 == touch_id)
2211+ continue;
2212+
2213+ for (unsigned int other_id_2 : free_touches_) {
2214+ if (other_id_2 == touch_id || other_id_2 == other_id_1)
2215+ continue;
2216+
2217+ uint64_t min_start_time = start_times_[touch_id];
2218+ if (start_times_[other_id_1] < min_start_time &&
2219+ unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end())
2220+ min_start_time = start_times_[other_id_1];
2221+ if (start_times_[other_id_2] < min_start_time &&
2222+ unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end())
2223+ min_start_time = start_times_[other_id_2];
2224+
2225+ if (start_times_[touch_id] - min_start_time < kCompositionTime) {
2226+ TouchSet set;
2227+ set.insert(touch_id);
2228+ set.insert(other_id_1);
2229+ set.insert(other_id_2);
2230+ utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_, subscription, set,
2231+ start_times_[touch_id]);
2232+ unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture));
2233+ }
2234+ }
2235+ }
2236+ }
2237+ }
2238+
2239+ void MatchFourTouchGestures(unsigned int touch_id) {
2240+ for( utouch::grail::UGSubscription* subscription : subscriptions_[3] ) {
2241+ for (unsigned int other_id_1 : free_touches_) {
2242+ if (other_id_1 == touch_id)
2243+ continue;
2244+
2245+ for (unsigned int other_id_2 : free_touches_) {
2246+ if (other_id_2 == touch_id || other_id_2 == other_id_1)
2247+ continue;
2248+
2249+ for (unsigned int other_id_3 : free_touches_) {
2250+ if (other_id_3 == touch_id || other_id_3 == other_id_1 ||
2251+ other_id_3 == other_id_2)
2252+ continue;
2253+
2254+ uint64_t min_start_time = start_times_[touch_id];
2255+ if (start_times_[other_id_1] < min_start_time &&
2256+ unaccepted_touches_.find(other_id_1) != unaccepted_touches_.end())
2257+ min_start_time = start_times_[other_id_1];
2258+ if (start_times_[other_id_2] < min_start_time &&
2259+ unaccepted_touches_.find(other_id_2) != unaccepted_touches_.end())
2260+ min_start_time = start_times_[other_id_2];
2261+ if (start_times_[other_id_3] < min_start_time &&
2262+ unaccepted_touches_.find(other_id_3) != unaccepted_touches_.end())
2263+ min_start_time = start_times_[other_id_3];
2264+
2265+ if (start_times_[touch_id] - min_start_time < kCompositionTime) {
2266+ TouchSet set;
2267+ set.insert(touch_id);
2268+ set.insert(other_id_1);
2269+ set.insert(other_id_2);
2270+ set.insert(other_id_3);
2271+ utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_,
2272+ subscription,
2273+ set,
2274+ start_times_[touch_id]);
2275+ unaccepted_gestures_.insert(utouch::grail::SharedGesture(gesture));
2276+ }
2277+ }
2278+ }
2279+ }
2280+ }
2281+ }
2282+
2283+ void MatchFiveTouchGestures(unsigned int touch_id) {
2284+ for (utouch::grail::UGSubscription* subscription : subscriptions_[4]) {
2285+ for (unsigned int other_id_1 : free_touches_) {
2286+ if (other_id_1 == touch_id)
2287+ continue;
2288+
2289+ for (unsigned int other_id_2 : free_touches_) {
2290+ if (other_id_2 == touch_id || other_id_2 == other_id_1)
2291+ continue;
2292+
2293+ for (unsigned int other_id_3 : free_touches_) {
2294+ if (other_id_3 == touch_id || other_id_3 == other_id_1 ||
2295+ other_id_3 == other_id_2)
2296+ continue;
2297+
2298+ for (unsigned int other_id_4 : free_touches_) {
2299+ if (other_id_4 == touch_id || other_id_4 == other_id_1 ||
2300+ other_id_4 == other_id_2 || other_id_4 == other_id_3)
2301+ continue;
2302+
2303+ uint64_t min_start_time = start_times_[touch_id];
2304+ if (start_times_[other_id_1] < min_start_time &&
2305+ unaccepted_touches_.find(other_id_1) !=
2306+ unaccepted_touches_.end())
2307+ min_start_time = start_times_[other_id_1];
2308+ if (start_times_[other_id_2] < min_start_time &&
2309+ unaccepted_touches_.find(other_id_2) !=
2310+ unaccepted_touches_.end())
2311+ min_start_time = start_times_[other_id_2];
2312+ if (start_times_[other_id_3] < min_start_time &&
2313+ unaccepted_touches_.find(other_id_3) !=
2314+ unaccepted_touches_.end())
2315+ min_start_time = start_times_[other_id_3];
2316+ if (start_times_[other_id_4] < min_start_time &&
2317+ unaccepted_touches_.find(other_id_4) !=
2318+ unaccepted_touches_.end())
2319+ min_start_time = start_times_[other_id_4];
2320+
2321+ if (start_times_[touch_id] - min_start_time < kCompositionTime) {
2322+ TouchSet set;
2323+ set.insert(touch_id);
2324+ set.insert(other_id_1);
2325+ set.insert(other_id_2);
2326+ set.insert(other_id_3);
2327+ set.insert(other_id_4);
2328+ utouch::grail::Gesture * gesture = new utouch::grail::Gesture(parent_, subscription, set,
2329+ start_times_[touch_id]);
2330+ unaccepted_gestures_.insert( utouch::grail::SharedGesture(gesture) );
2331+ }
2332+ }
2333+ }
2334+ }
2335+ }
2336+ }
2337+ }
2338+
2339+ void ProcessEvent(const UFEvent& event) {
2340+ UFFrame frame;
2341+ UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
2342+ &frame);
2343+ if (status != UFStatusSuccess) {
2344+ fprintf(stderr, "Warning: failed to get frame from event\n");
2345+ return;
2346+ }
2347+
2348+ TouchSet modified_touches;
2349+ TouchSet ended_touches;
2350+ GetModifiedAndEndedTouches(frame, &modified_touches,
2351+ &ended_touches, frame_event_get_time(event));
2352+
2353+ for (auto it = accepted_gestures_.begin(); it != accepted_gestures_.end(); ) {
2354+ const utouch::grail::SharedGesture & gesture = *it++;
2355+ gesture->Update(event, modified_touches);
2356+ if (gesture->ended()) {
2357+ for (unsigned int touch_id : gesture->touches())
2358+ free_touches_.insert(touch_id);
2359+ accepted_gestures_.erase(gesture);
2360+ }
2361+ }
2362+
2363+ for (auto it = unaccepted_gestures_.begin();
2364+ it != unaccepted_gestures_.end();
2365+ ) {
2366+ const utouch::grail::SharedGesture & gesture = *it++;
2367+ gesture->Update(event, modified_touches);
2368+ if (gesture->canceled())
2369+ RejectGesture(gesture);
2370+ }
2371+
2372+ for (unsigned int touch_id : ended_touches)
2373+ free_touches_.erase(touch_id);
2374+ }
2375+
2376+
2377+
2378+ void RejectGesture(const utouch::grail::SharedGesture& gesture) {
2379+ gesture->Cancel();
2380+ handle_->RemoveGestureFromEventQueue(gesture->id());
2381+ unaccepted_gestures_.erase(gesture);
2382+ }
2383+
2384+ Recognizer * parent_;
2385+
2386+ utouch::grail::UGHandle * const handle_;
2387+ const UFDevice device_;
2388+ const Window window_;
2389+ float device_x_res_; /* Units of pixel/mm */
2390+ float device_y_res_;
2391+ bool device_direct_;
2392+ std::set<utouch::grail::UGSubscription*> subscriptions_[5];
2393+ std::set<utouch::grail::SharedGesture> unaccepted_gestures_;
2394+ std::set<utouch::grail::SharedGesture> accepted_gestures_;
2395+ std::map<unsigned int, uint64_t> start_times_;
2396+ TouchSet unaccepted_touches_;
2397+ TouchSet accepted_touches_;
2398+ TouchSet free_touches_;
2399+
2400+ };
2401+
2402+ Recognizer::Recognizer( utouch::grail::UGHandle * handle, const UFDevice device, Window window)
2403+ : d_( new Private( this, handle, device, window ) ) {
2404+ }
2405+
2406+ void Recognizer::ActivateSubscription( utouch::grail::UGSubscription * subscription) {
2407+ d_->subscriptions_[subscription->touches_start() - 1].insert(subscription);
2408+ }
2409+
2410+ void Recognizer::DeactivateSubscription( utouch::grail::UGSubscription * subscription) {
2411+ d_->subscriptions_[subscription->touches_start() - 1].erase(subscription);
2412+
2413+ for (auto it = d_->unaccepted_gestures_.begin();
2414+ it != d_->unaccepted_gestures_.end();
2415+ ) {
2416+ const utouch::grail::SharedGesture & gesture = *it++;
2417+ if (gesture->subscription() == subscription)
2418+ gesture->Cancel();
2419+ d_->unaccepted_gestures_.erase(gesture);
2420+ }
2421+
2422+ for (auto it = d_->accepted_gestures_.begin(); it != d_->accepted_gestures_.end(); ) {
2423+ const utouch::grail::SharedGesture& gesture = *it++;
2424+ if (gesture->subscription() == subscription)
2425+ gesture->Cancel();
2426+ d_->accepted_gestures_.erase(gesture);
2427+ }
2428+ }
2429+
2430+ void Recognizer::ProcessFrameEvent(const UFEvent event) {
2431+ UpdateTime(frame_event_get_time(event));
2432+ d_->MatchSubscriptionsForEvent(event);
2433+ d_->ProcessEvent(event);
2434+ }
2435+
2436+ void Recognizer::UpdateTime(uint64_t time) {
2437+ for (auto it = d_->unaccepted_gestures_.begin();
2438+ it != d_->unaccepted_gestures_.end();
2439+ ) {
2440+ const utouch::grail::SharedGesture & gesture = *it++;
2441+ uint64_t timeout = gesture->Timeout();
2442+ if (timeout && time - gesture->start_time() > timeout)
2443+ d_->RejectGesture(gesture);
2444+ }
2445+
2446+ for (auto it = d_->unaccepted_touches_.begin(); it
2447+ != d_->unaccepted_touches_.end();
2448+ ) {
2449+ unsigned int touch_id = *it++;
2450+ if (time - d_->start_times_[touch_id] < kCompositionTime)
2451+ continue;
2452+
2453+ for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_)
2454+ if (gesture->touches().find(touch_id) != gesture->touches().end())
2455+ goto next_touch;
2456+
2457+ frame_x11_reject_touch(d_->device_, d_->window_, touch_id);
2458+ d_->unaccepted_touches_.erase(touch_id);
2459+ d_->free_touches_.erase(touch_id);
2460+
2461+ next_touch: ;
2462+ }
2463+ }
2464+
2465+ uint64_t Recognizer::NextTimeout() {
2466+ uint64_t min_timeout = std::numeric_limits<uint64_t>::max();
2467+ for (unsigned int touch_id : d_->unaccepted_touches_)
2468+ if (kCompositionTime + d_->start_times_[touch_id] < min_timeout)
2469+ min_timeout = d_->start_times_[touch_id] + kCompositionTime;
2470+
2471+ for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_) {
2472+ uint64_t timeout = gesture->Timeout();
2473+ if (timeout && gesture->start_time() + timeout < min_timeout)
2474+ min_timeout = gesture->start_time() + timeout;
2475+ }
2476+
2477+ return min_timeout;
2478+ }
2479+
2480+ UGStatus Recognizer::AcceptGesture(unsigned int id) {
2481+ utouch::grail::SharedGesture gesture;
2482+ for (const utouch::grail::SharedGesture & test_gesture : d_->unaccepted_gestures_) {
2483+ if (test_gesture->id() == id) {
2484+ gesture = test_gesture;
2485+ break;
2486+ }
2487+ }
2488+
2489+ if (!gesture)
2490+ return UGStatusErrorInvalidGesture;
2491+
2492+ for (unsigned int touch_id : gesture->touches()) {
2493+ if (d_->accepted_touches_.find(touch_id) == d_->accepted_touches_.end()) {
2494+ frame_x11_accept_touch(d_->device_, d_->window_, touch_id);
2495+ d_->accepted_touches_.insert(touch_id);
2496+ d_->unaccepted_touches_.erase(touch_id);
2497+ } else {
2498+ for (auto it = d_->accepted_gestures_.begin();
2499+ it != d_->accepted_gestures_.end();
2500+ ) {
2501+ const utouch::grail::SharedGesture & other_gesture = *it++;
2502+ const TouchSet& other_touches = other_gesture->touches();
2503+ if (other_touches.find(touch_id) != other_touches.end()) {
2504+ gesture->Cancel();
2505+ d_->handle_->RemoveGestureFromEventQueue(other_gesture->id());
2506+ d_->accepted_gestures_.erase(other_gesture);
2507+ }
2508+ }
2509+ }
2510+
2511+ d_->free_touches_.erase(touch_id);
2512+ }
2513+
2514+ for (auto it = d_->unaccepted_gestures_.begin();
2515+ it != d_->unaccepted_gestures_.end();
2516+ ) {
2517+ const utouch::grail::SharedGesture & other_gesture = *it++;
2518+ if (other_gesture == gesture)
2519+ continue;
2520+ for (unsigned int touch_id : other_gesture->touches()) {
2521+ if (gesture->touches().find(touch_id) != gesture->touches().end()) {
2522+ d_->RejectGesture(other_gesture);
2523+ break;
2524+ }
2525+ }
2526+ }
2527+
2528+ d_->accepted_gestures_.insert(gesture);
2529+ d_->unaccepted_gestures_.erase(gesture);
2530+
2531+ return UGStatusSuccess;
2532+ }
2533+
2534+ UGStatus Recognizer::RejectGesture(unsigned int id) {
2535+ for (const utouch::grail::SharedGesture & gesture : d_->unaccepted_gestures_) {
2536+ if (gesture->id() == id) {
2537+ d_->RejectGesture(gesture);
2538+ return UGStatusSuccess;
2539+ }
2540+ }
2541+
2542+ return UGStatusErrorInvalidGesture;
2543+ }
2544+
2545+ utouch::grail::UGHandle * Recognizer::handle() const {
2546+ return d_->handle_;
2547+ }
2548+
2549+ float Recognizer::device_x_res() const {
2550+ return d_->device_x_res_;
2551+ }
2552+
2553+ float Recognizer::device_y_res() const {
2554+ return d_->device_y_res_;
2555+ }
2556+
2557+ bool Recognizer::device_direct() const {
2558+ return d_->device_direct_;
2559+ }
2560+
2561+ Recognizer::~Recognizer() {
2562+ for (const utouch::grail::SharedGesture& gesture : d_->unaccepted_gestures_)
2563+ gesture->Cancel();
2564+
2565+ for (const utouch::grail::SharedGesture& gesture : d_->accepted_gestures_)
2566+ gesture->Cancel();
2567+ }
2568+ }
2569 }
2570
2571=== modified file 'src/v3/recognizer.h'
2572--- src/v3/recognizer.h 2011-10-19 22:07:30 +0000
2573+++ src/v3/recognizer.h 2011-11-01 21:20:40 +0000
2574@@ -32,57 +32,44 @@
2575 #include "utouch/grail.h"
2576 #include "v3/subscription.h"
2577
2578-class Gesture;
2579-class UGHandle_;
2580-
2581-typedef std::set<unsigned int> TouchSet;
2582-typedef std::shared_ptr<Gesture> SharedGesture;
2583-
2584-class Recognizer {
2585- public:
2586- Recognizer(UGHandle_* handle, const UFDevice device, Window window);
2587- ~Recognizer();
2588-
2589- void ActivateSubscription(UGSubscription_* subscription);
2590- void DeactivateSubscription(UGSubscription_* subscription);
2591- void ProcessFrameEvent(const UFEvent event);
2592- void UpdateTime(uint64_t time);
2593- uint64_t NextTimeout();
2594- UGStatus AcceptGesture(unsigned int id);
2595- UGStatus RejectGesture(unsigned int id);
2596-
2597- UGHandle_* handle() const { return handle_; }
2598- float device_x_res() const { return device_x_res_; }
2599- float device_y_res() const { return device_y_res_; }
2600- bool device_direct() const { return device_direct_; }
2601-
2602- Recognizer(const Recognizer&) = delete;
2603- void operator=(const Recognizer&) = delete;
2604-
2605- private:
2606- UGHandle_* const handle_;
2607- const UFDevice device_;
2608- const Window window_;
2609- float device_x_res_; /* Units of pixel/mm */
2610- float device_y_res_;
2611- bool device_direct_;
2612- std::set<UGSubscription_*> subscriptions_[5];
2613- std::set<SharedGesture> unaccepted_gestures_;
2614- std::set<SharedGesture> accepted_gestures_;
2615- std::map<unsigned int, uint64_t> start_times_;
2616- TouchSet unaccepted_touches_;
2617- TouchSet accepted_touches_;
2618- TouchSet free_touches_;
2619-
2620- void MatchSubscriptionsForEvent(const UFEvent event);
2621- void MatchSubscriptionsForTouch(unsigned int touch_id);
2622- void MatchOneTouchGestures(unsigned int touch_id);
2623- void MatchTwoTouchGestures(unsigned int touch_id);
2624- void MatchThreeTouchGestures(unsigned int touch_id);
2625- void MatchFourTouchGestures(unsigned int touch_id);
2626- void MatchFiveTouchGestures(unsigned int touch_id);
2627- void ProcessEvent(const UFEvent& event);
2628- void RejectGesture(const SharedGesture& gesture);
2629-};
2630-
2631+namespace utouch {
2632+ namespace grail {
2633+
2634+ class UGHandle;
2635+ class UGSubscription;
2636+
2637+ class Gesture;
2638+ typedef std::shared_ptr<Gesture> SharedGesture;
2639+
2640+ typedef std::set<unsigned int> TouchSet;
2641+
2642+ class Recognizer {
2643+ public:
2644+ Recognizer( utouch::grail::UGHandle * handle, const UFDevice device, Window window);
2645+ ~Recognizer();
2646+
2647+ void ActivateSubscription( utouch::grail::UGSubscription * subscription );
2648+ void DeactivateSubscription( utouch::grail::UGSubscription* subscription);
2649+ void ProcessFrameEvent(const UFEvent event);
2650+ void UpdateTime(uint64_t time);
2651+ uint64_t NextTimeout();
2652+ UGStatus AcceptGesture(unsigned int id);
2653+ UGStatus RejectGesture(unsigned int id);
2654+
2655+ utouch::grail::UGHandle * handle() const;
2656+ float device_x_res() const;
2657+ float device_y_res() const;
2658+ bool device_direct() const;
2659+
2660+ Recognizer(const Recognizer&) = delete;
2661+ void operator=(const Recognizer&) = delete;
2662+
2663+ protected:
2664+
2665+ struct Private;
2666+ std::shared_ptr< Private > d_;
2667+
2668+ };
2669+ }
2670+}
2671 #endif // UTOUCH_GRAIL_RECOGNIZER_H_
2672
2673=== modified file 'src/v3/slice.cpp'
2674--- src/v3/slice.cpp 2011-10-21 00:06:58 +0000
2675+++ src/v3/slice.cpp 2011-11-01 21:20:40 +0000
2676@@ -21,10 +21,10 @@
2677
2678 #include "v3/slice.h"
2679
2680-#include <assert.h>
2681-#include <math.h>
2682-#include <stdio.h>
2683-#include <string.h>
2684+#include <cassert>
2685+#include <cmath>
2686+#include <cstdio>
2687+#include <cstring>
2688
2689 #include <utouch/frame.h>
2690
2691@@ -32,550 +32,687 @@
2692 #include "v3/recognizer.h"
2693 #include "v3/subscription.h"
2694
2695-namespace {
2696-
2697-const UGTransform kIdentityTransform = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
2698-
2699-} // namespace
2700-
2701-UGSlice_::UGSlice_(const SharedGesture& gesture, UFEvent event,
2702- const TouchSet& touches, UGGestureTypeMask recognized)
2703- : gesture_(gesture),
2704- event_(event),
2705- frame_(NULL),
2706- touches_(touches),
2707- time_(frame_event_get_time(event)),
2708- state_(UGGestureStateBegin),
2709- original_center_x_(0),
2710- original_center_y_(0),
2711- original_radius_(0),
2712- original_angle_(0),
2713- radius_(0),
2714- angle_(0),
2715- center_of_rotation_x_(0),
2716- center_of_rotation_y_(0),
2717- recognized_(recognized),
2718- touch_count_changed_(false) {
2719- frame_event_ref(event);
2720-
2721- memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform));
2722- memcpy(cumulative_transform_, kIdentityTransform, sizeof(kIdentityTransform));
2723-}
2724-
2725-UGSlice_* UGSlice_::NewUGSlice_(const SharedGesture& gesture, UFEvent event,
2726- const TouchSet& touches,
2727- UGGestureTypeMask recognized) {
2728- UGSlice_* slice = new UGSlice_(gesture, event, touches, recognized);
2729-
2730- UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
2731- &slice->frame_);
2732- if (status != UFStatusSuccess) {
2733- fprintf(stderr, "Warning: failed to get frame from event\n");
2734- delete slice;
2735- return NULL;
2736- }
2737-
2738- slice->GetValues(touches, &slice->original_center_x_,
2739- &slice->original_center_y_, &slice->original_radius_,
2740- &slice->original_angle_, true);
2741- slice->radius_ = slice->original_radius_;
2742- slice->angle_ = slice->original_angle_;
2743-
2744- return slice;
2745-}
2746-
2747-UGSlice_::UGSlice_(const SharedUGSlice_& prev, UFEvent event,
2748- const TouchSet& touches)
2749- : gesture_(prev->gesture_),
2750- event_(event ? : NULL),
2751- frame_(NULL),
2752- touches_(touches),
2753- time_(frame_event_get_time(event)),
2754- state_(UGGestureStateUpdate),
2755- original_center_x_(prev->original_center_x_),
2756- original_center_y_(prev->original_center_y_),
2757- original_radius_(prev->original_radius_),
2758- original_angle_(prev->original_angle_),
2759- radius_(prev->radius_),
2760- angle_(prev->angle_),
2761- center_of_rotation_x_(0),
2762- center_of_rotation_y_(0),
2763- recognized_(prev->recognized_),
2764- touch_count_changed_(touches_.size() != prev->touches_.size()) {
2765- memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform));
2766-
2767- if (touch_count_changed_) {
2768- memcpy(cumulative_transform_, kIdentityTransform,
2769- sizeof(kIdentityTransform));
2770- original_radius_ = 0;
2771- original_angle_ = 0;
2772- } else {
2773- memcpy(cumulative_transform_, prev->cumulative_transform_,
2774- sizeof(prev->cumulative_transform_));
2775- }
2776-
2777- if (event_)
2778- frame_event_ref(event_);
2779-}
2780-
2781-UGSlice_* UGSlice_::NewUGSlice_(const SharedUGSlice_& prev, UFEvent event,
2782- const TouchSet& touches) {
2783- UGSlice_* slice = new UGSlice_(prev, event, touches);
2784-
2785- UFStatus status = frame_event_get_property(event, UFEventPropertyFrame,
2786- &slice->frame_);
2787- if (status != UFStatusSuccess) {
2788- fprintf(stderr, "Warning: failed to get frame from event\n");
2789- delete slice;
2790- return NULL;
2791- }
2792-
2793- if (slice->touch_count_changed_) {
2794- slice->GetValues(touches, &slice->original_center_x_,
2795- &slice->original_center_y_, &slice->original_radius_,
2796- &slice->original_angle_, true);
2797- slice->radius_ = slice->original_radius_;
2798- slice->angle_ = slice->original_angle_;
2799- } else {
2800- slice->SetTransforms();
2801- slice->SetCenterOfRotation();
2802- slice->CheckGestureEnd();
2803- }
2804-
2805- return slice;
2806-}
2807-
2808-void UGSlice_::GetValues(const TouchSet& touches, float* x, float* y,
2809- float* radius, float* angle, bool init) {
2810- *x = 0;
2811- *y = 0;
2812-
2813- for (unsigned int touch_id : touches) {
2814- UFTouch touch;
2815- UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
2816- if (status != UFStatusSuccess) {
2817- fprintf(stderr, "Warning: failed to get touch from frame\n");
2818- continue;
2819- }
2820-
2821- if (gesture_.lock()->recognizer().device_direct()) {
2822- *x += frame_touch_get_window_x(touch);
2823- *y += frame_touch_get_window_y(touch);
2824- } else {
2825- *x += frame_touch_get_device_x(touch);
2826- *y += frame_touch_get_device_y(touch);
2827- }
2828- }
2829-
2830- *x /= touches.size();
2831- *y /= touches.size();
2832-
2833- if (touches.size() == 1)
2834- return;
2835-
2836- *radius = 0;
2837- *angle = 0;
2838- int num_angles = 0;
2839- for (unsigned int touch_id : touches) {
2840- UFTouch touch;
2841- float cur_x;
2842- float cur_y;
2843-
2844- UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
2845- if (status != UFStatusSuccess) {
2846- fprintf(stderr, "Warning: failed to get touch from frame\n");
2847- continue;
2848- }
2849-
2850- if (gesture_.lock()->recognizer().device_direct()) {
2851- cur_x = frame_touch_get_window_x(touch);
2852- cur_y = frame_touch_get_window_y(touch);
2853- } else {
2854- cur_x = frame_touch_get_device_x(touch);
2855- cur_y = frame_touch_get_device_y(touch);
2856- }
2857-
2858- *radius += sqrtf((cur_x - *x) * (cur_x - *x) + (cur_y - *y) * (cur_y - *y));
2859-
2860- float new_angle = atan2f(cur_y - *y, cur_x - *x);
2861-
2862- if (init) {
2863- *angle += new_angle;
2864- num_angles++;
2865- } else if (frame_touch_get_state(touch) != UFTouchStateBegin) {
2866- float prev_angle = gesture_.lock()->AngleForTouch(touch_id);
2867-
2868- if (new_angle - prev_angle < -M_PI)
2869- new_angle += 2 * M_PI;
2870- else if (new_angle - prev_angle > M_PI)
2871- new_angle -= 2 * M_PI;
2872-
2873- *angle += new_angle - prev_angle;
2874- num_angles++;
2875- }
2876-
2877- gesture_.lock()->SetAngleForTouch(touch_id, new_angle);
2878- }
2879-
2880- *radius /= touches.size();
2881- *angle /= num_angles;
2882- if (!init)
2883- *angle += angle_;
2884-}
2885-
2886-void UGSlice_::SetTransforms() {
2887- float center_x;
2888- float center_y;
2889- float new_radius = radius_;
2890- float new_angle = angle_;
2891- GetValues(touches_, &center_x, &center_y, &new_radius, &new_angle, false);
2892-
2893- if (!touch_count_changed_) {
2894- float scale = radius_ ? new_radius / radius_ : 1;
2895-
2896- transform_[0][0] = cosf(new_angle - angle_) * scale;
2897- transform_[0][1] = -sinf(new_angle - angle_) * scale;
2898- transform_[0][2] =
2899- center_x - cumulative_transform_[0][2] - original_center_x_;
2900- transform_[1][0] = -transform_[0][1];
2901- transform_[1][1] = transform_[0][0];
2902- transform_[1][2] =
2903- center_y - cumulative_transform_[1][2] - original_center_y_;
2904-
2905- scale = original_radius_ ? new_radius / original_radius_ : 1;
2906-
2907- cumulative_transform_[0][0] = cosf(new_angle - original_angle_) * scale;
2908- cumulative_transform_[0][1] = -sinf(new_angle - original_angle_) * scale;
2909- cumulative_transform_[0][2] = center_x - original_center_x_;
2910- cumulative_transform_[1][0] = -cumulative_transform_[0][1];
2911- cumulative_transform_[1][1] = cumulative_transform_[0][0];
2912- cumulative_transform_[1][2] = center_y - original_center_y_;
2913- } else {
2914- original_radius_ += new_radius - radius_;
2915- original_angle_ += new_angle - angle_;
2916- original_center_x_ +=
2917- center_x - (original_center_x_ + cumulative_transform_[0][2]);
2918- original_center_y_ +=
2919- center_y - (original_center_y_ + cumulative_transform_[1][2]);
2920- }
2921-
2922- radius_ = new_radius;
2923- angle_ = new_angle;
2924-}
2925-
2926-/**
2927- * Determine the center of rotation point.
2928- *
2929- * For any given point q that is transformed by a 2D affine transformation
2930- * matrix T about anchor point P the new point q' may be determined by the
2931- * following equation:
2932- *
2933- * q' = T * (q - P) + P
2934- *
2935- * T and P are dependent, so we can modify one and find a new value for the
2936- * other. We will label the original T and P as T0 and P0, and the new values
2937- * will be labeled T1 and P1. We can find new values by solving the following
2938- * equation:
2939- *
2940- * q' = T0 * (q - P0) + P0 = T1 * (q - P1) + P1
2941- *
2942- * In the calculations below, we use variables for the scalar values
2943- * that make up T0, P0, T1, and P1:
2944- *
2945- * T0: [ a -b c ] P0: [ x0 ] T1: [ a -b 0 ] P1: [ x1 ]
2946- * [ b a d ] [ y0 ] [ b a 0 ] [ y1 ]
2947- * [ 0 0 1 ] [ 0 ] [ 0 0 1 ] [ 0 ]
2948- *
2949- * Note that rotation and scaling are independent of the anchor point, so a and
2950- * b are equivalent between the transformation matrices.
2951- *
2952- * Since we know all the values of T0, P0, and T1, we can calculate the values
2953- * x1 and y1 in P1.
2954- */
2955-void UGSlice_::SetCenterOfRotation() {
2956- float a = transform_[0][0];
2957- float b = transform_[1][0];
2958- float c = transform_[0][2];
2959- float d = transform_[0][2];
2960- float x0 = original_center_x_ + cumulative_transform_[0][2];
2961- float y0 = original_center_y_ + cumulative_transform_[1][2];
2962- float x1;
2963- float y1;
2964-
2965- float div = a*a - 2*a + b*b + 1;
2966-
2967- if (fabsf(div) < 1e-5)
2968- return;
2969-
2970- x1 = (a*a*x0 - a*(2*x0+c) + b*b*x0 - b*d + c + x0) / div;
2971- y1 = (a*a*y0 - a*(2*y0+d) + b*b*y0 + b*c + d + y0) / div;
2972-
2973- center_of_rotation_x_ = x1;
2974- center_of_rotation_y_ = y1;
2975-}
2976-
2977-void UGSlice_::CheckGestureEnd() {
2978- unsigned int num_active_touches = 0;
2979- for (unsigned int touch_id : touches_) {
2980- UFTouch touch;
2981- UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
2982- if (status != UFStatusSuccess) {
2983- fprintf(stderr, "Warning: failed to get touch from frame by id\n");
2984- continue;
2985- }
2986-
2987- if (frame_touch_get_state(touch) == UFTouchStateEnd) {
2988- continue;
2989- } else {
2990- int pending_end;
2991- status = frame_touch_get_property(touch, UFTouchPropertyPendingEnd,
2992- &pending_end);
2993- if (status != UFStatusSuccess) {
2994- fprintf(stderr, "Warning: failed to get touch pending end property\n");
2995- continue;
2996- }
2997-
2998- if (pending_end)
2999- continue;
3000- }
3001-
3002- num_active_touches++;
3003- }
3004-
3005- const UGSubscription_* subscription = gesture_.lock()->subscription();
3006- unsigned int touches_start = subscription->touches_start();
3007- unsigned int touches_min = subscription->touches_min();
3008- if ((!touches_min && num_active_touches < touches_start) ||
3009- (touches_min && num_active_touches < touches_min))
3010- state_ = UGGestureStateEnd;
3011-}
3012-
3013-uint64_t UGSlice_::CumulativeTime() const {
3014- return time_ - gesture_.lock()->start_time();
3015-}
3016-
3017-float UGSlice_::CumulativeDrag2() const {
3018- float res_x = gesture_.lock()->recognizer().device_x_res();
3019- float res_y = gesture_.lock()->recognizer().device_y_res();
3020-
3021- return fabsf(cumulative_transform_[0][2] / res_x *
3022- cumulative_transform_[0][2] / res_x +
3023- cumulative_transform_[1][2] / res_y *
3024- cumulative_transform_[1][2] / res_y);
3025-}
3026-
3027-float UGSlice_::CumulativePinch() const {
3028- float pinch = original_radius_ ? radius_ / original_radius_ : 1;
3029-
3030- return (pinch >= 1 ? pinch : 1 / pinch);
3031-}
3032-
3033-UGGestureTypeMask UGSlice_::CheckRecognition(
3034- const UGSubscription_& subscription) {
3035- if ((subscription.mask() & UGGestureTypeDrag) &&
3036- (!subscription.drag().timeout() ||
3037- CumulativeTime() < subscription.drag().timeout()) &&
3038- CumulativeDrag2() > subscription.drag().threshold())
3039- recognized_ |= UGGestureTypeDrag;
3040-
3041- if ((subscription.mask() & UGGestureTypePinch) &&
3042- (!subscription.pinch().timeout() ||
3043- CumulativeTime() < subscription.pinch().timeout()) &&
3044- CumulativePinch() > subscription.pinch().threshold())
3045- recognized_ |= UGGestureTypePinch;
3046-
3047- if ((subscription.mask() & UGGestureTypeRotate) &&
3048- (!subscription.rotate().timeout() ||
3049- CumulativeTime() < subscription.rotate().timeout()) &&
3050- fabsf(angle_ - original_angle_) > subscription.rotate().threshold())
3051- recognized_ |= UGGestureTypeRotate;
3052-
3053- if ((subscription.mask() & UGGestureTypeTap) &&
3054- CumulativeTime() < subscription.tap().timeout() &&
3055- state_ == UGGestureStateEnd)
3056- recognized_ |= UGGestureTypeTap;
3057-
3058- if (subscription.mask() & UGGestureTypeTouch)
3059- recognized_ |= UGGestureTypeTouch;
3060-
3061- return recognized_;
3062-}
3063-
3064-UGStatus UGSlice_::GetTouchId(unsigned int index, void* touch_id) const {
3065- auto it = touches_.begin();
3066- for (unsigned int i = 0; i < index; ++i, ++it)
3067- if (it == touches_.end())
3068- return UGStatusErrorInvalidIndex;
3069-
3070- *reinterpret_cast<unsigned int*>(touch_id) = *it;
3071- return UGStatusSuccess;
3072-}
3073-
3074-UGStatus UGSlice_::GetProperty(UGSliceProperty property, void* value) const {
3075- switch (property) {
3076- case UGSlicePropertyId:
3077- *reinterpret_cast<unsigned int*>(value) = gesture_.lock()->id();
3078- return UGStatusSuccess;
3079-
3080- case UGSlicePropertyState:
3081- *reinterpret_cast<UGGestureState*>(value) = state_;
3082- return UGStatusSuccess;
3083-
3084- case UGSlicePropertySubscription:
3085- *reinterpret_cast<UGSubscription*>(value) = gesture_.lock()->subscription();
3086- return UGStatusSuccess;
3087-
3088- case UGSlicePropertyRecognized:
3089- *reinterpret_cast<UGGestureTypeMask*>(value) = recognized_;
3090- return UGStatusSuccess;
3091-
3092- case UGSlicePropertyNumTouches:
3093- *reinterpret_cast<unsigned int*>(value) = touches_.size();
3094- return UGStatusSuccess;
3095-
3096- case UGSlicePropertyFrame:
3097- *reinterpret_cast<UFFrame*>(value) = frame_;
3098- return UGStatusSuccess;
3099-
3100- case UGSlicePropertyOriginalCenterX:
3101- *reinterpret_cast<float*>(value) = original_center_x_;
3102- return UGStatusSuccess;
3103-
3104- case UGSlicePropertyOriginalCenterY:
3105- *reinterpret_cast<float*>(value) = original_center_y_;
3106- return UGStatusSuccess;
3107-
3108- case UGSlicePropertyOriginalRadius:
3109- *reinterpret_cast<float*>(value) = original_radius_;
3110- return UGStatusSuccess;
3111-
3112- case UGSlicePropertyTransform:
3113- *reinterpret_cast<UGTransform**>(value) = &transform_;
3114- return UGStatusSuccess;
3115-
3116- case UGSlicePropertyCumulativeTransform:
3117- *reinterpret_cast<UGTransform**>(value) = &cumulative_transform_;
3118- return UGStatusSuccess;
3119-
3120- case UGSlicePropertyCenterOfRotationX:
3121- *reinterpret_cast<float*>(value) = center_of_rotation_x_;
3122- return UGStatusSuccess;
3123-
3124- case UGSlicePropertyCenterOfRotationY:
3125- *reinterpret_cast<float*>(value) = center_of_rotation_y_;
3126- return UGStatusSuccess;
3127- }
3128-
3129- return UGStatusErrorUnknownProperty;
3130-}
3131-
3132-UGSlice_::~UGSlice_() {
3133- frame_event_unref(event_);
3134-}
3135-
3136-extern "C" {
3137-
3138-UGStatus grail_slice_get_property(const UGSlice slice, UGSliceProperty property,
3139- void* value) {
3140- return slice->GetProperty(property, value);
3141-}
3142-
3143-unsigned int grail_slice_get_id(const UGSlice slice) {
3144- unsigned int id;
3145- UGStatus status = slice->GetProperty(UGSlicePropertyId, &id);
3146- assert(status == UGStatusSuccess);
3147- return id;
3148-}
3149-
3150-UGGestureState grail_slice_get_state(const UGSlice slice) {
3151- UGGestureState state;
3152- UGStatus status = slice->GetProperty(UGSlicePropertyState, &state);
3153- assert(status == UGStatusSuccess);
3154- return state;
3155-}
3156-
3157-UGGestureTypeMask grail_slice_get_recognized(const UGSlice slice) {
3158- UGGestureTypeMask mask;
3159- UGStatus status = slice->GetProperty(UGSlicePropertyRecognized, &mask);
3160- assert(status == UGStatusSuccess);
3161- return mask;
3162-}
3163-
3164-UGSubscription grail_slice_get_subscription(const UGSlice slice) {
3165- UGSubscription subscription;
3166- UGStatus status = slice->GetProperty(UGSlicePropertySubscription,
3167- &subscription);
3168- assert(status == UGStatusSuccess);
3169- return subscription;
3170-}
3171-
3172-unsigned int grail_slice_get_num_touches(const UGSlice slice) {
3173- unsigned int num_touches;
3174- UGStatus status = slice->GetProperty(UGSlicePropertyNumTouches, &num_touches);
3175- assert(status == UGStatusSuccess);
3176- return num_touches;
3177-}
3178-
3179-UGStatus grail_slice_get_touch_id(const UGSlice slice, unsigned int index,
3180- void *touch_id) {
3181- return slice->GetTouchId(index, touch_id);
3182-}
3183-
3184-float grail_slice_get_original_center_x(const UGSlice slice) {
3185- float x;
3186- UGStatus status = slice->GetProperty(UGSlicePropertyOriginalCenterX, &x);
3187- assert(status == UGStatusSuccess);
3188- return x;
3189-}
3190-
3191-float grail_slice_get_original_center_y(const UGSlice slice) {
3192- float y;
3193- UGStatus status = slice->GetProperty(UGSlicePropertyOriginalCenterY, &y);
3194- assert(status == UGStatusSuccess);
3195- return y;
3196-}
3197-
3198-float grail_slice_get_original_radius(const UGSlice slice) {
3199- float radius;
3200- UGStatus status = slice->GetProperty(UGSlicePropertyOriginalRadius, &radius);
3201- assert(status == UGStatusSuccess);
3202- return radius;
3203-}
3204-
3205-float grail_slice_get_center_of_rotation_x(const UGSlice slice) {
3206- float x;
3207- UGStatus status = slice->GetProperty(UGSlicePropertyCenterOfRotationX, &x);
3208- assert(status == UGStatusSuccess);
3209- return x;
3210-}
3211-
3212-float grail_slice_get_center_of_rotation_y(const UGSlice slice) {
3213- float y;
3214- UGStatus status = slice->GetProperty(UGSlicePropertyCenterOfRotationY, &y);
3215- assert(status == UGStatusSuccess);
3216- return y;
3217-}
3218-
3219-const UGTransform *grail_slice_get_transform(const UGSlice slice) {
3220- UGTransform *transform;
3221- UGStatus status = slice->GetProperty(UGSlicePropertyTransform, &transform);
3222- assert(status == UGStatusSuccess);
3223- return transform;
3224-}
3225-
3226-const UGTransform *grail_slice_get_cumulative_transform(const UGSlice slice) {
3227- UGTransform *transform;
3228- UGStatus status = slice->GetProperty(UGSlicePropertyCumulativeTransform,
3229- &transform);
3230- assert(status == UGStatusSuccess);
3231- return transform;
3232-}
3233-
3234-const UFFrame grail_slice_get_frame(const UGSlice slice) {
3235- UFFrame frame;
3236- UGStatus status = slice->GetProperty(UGSlicePropertyFrame, &frame);
3237- assert(status == UGStatusSuccess);
3238- return frame;
3239-}
3240-
3241-} // extern "C"
3242+namespace utouch {
3243+ namespace grail {
3244+
3245+ const UGTransform kIdentityTransform = {
3246+ { 1, 0, 0 },
3247+ { 0, 1, 0 },
3248+ { 0, 0, 1 }
3249+ };
3250+
3251+ struct UGSlice::Private {
3252+
3253+ Private( const SharedUGSlice & prev,
3254+ UFEvent event,
3255+ const TouchSet & touches )
3256+ : gesture_(prev->d_->gesture_),
3257+ event_(event ? : NULL),
3258+ frame_(NULL),
3259+ touches_(touches),
3260+ time_(frame_event_get_time(event)),
3261+ state_(UGGestureStateUpdate),
3262+ original_center_x_(prev->d_->original_center_x_),
3263+ original_center_y_(prev->d_->original_center_y_),
3264+ original_radius_(prev->d_->original_radius_),
3265+ original_angle_(prev->d_->original_angle_),
3266+ radius_(prev->d_->radius_),
3267+ angle_(prev->d_->angle_),
3268+ center_of_rotation_x_(0),
3269+ center_of_rotation_y_(0),
3270+ recognized_(prev->d_->recognized_),
3271+ touch_count_changed_(touches_.size() != prev->d_->touches_.size()) {
3272+
3273+ ::memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform));
3274+
3275+ if( touch_count_changed_ ) {
3276+ ::memcpy( cumulative_transform_,
3277+ kIdentityTransform,
3278+ sizeof( kIdentityTransform )
3279+ );
3280+ original_radius_ = 0;
3281+ original_angle_ = 0;
3282+ } else {
3283+ memcpy( cumulative_transform_,
3284+ prev->d_->cumulative_transform_,
3285+ sizeof(prev->d_->cumulative_transform_)
3286+ );
3287+ }
3288+
3289+ if (event_)
3290+ frame_event_ref(event_);
3291+ }
3292+
3293+ Private( const SharedGesture & gesture,
3294+ UFEvent event,
3295+ const TouchSet & touches,
3296+ UGGestureTypeMask recognized )
3297+ : gesture_(gesture),
3298+ event_(event),
3299+ frame_(NULL),
3300+ touches_(touches),
3301+ time_(frame_event_get_time(event)),
3302+ state_(UGGestureStateBegin),
3303+ original_center_x_(0),
3304+ original_center_y_(0),
3305+ original_radius_(0),
3306+ original_angle_(0),
3307+ radius_(0),
3308+ angle_(0),
3309+ center_of_rotation_x_(0),
3310+ center_of_rotation_y_(0),
3311+ recognized_(recognized),
3312+ touch_count_changed_(false) {
3313+
3314+ frame_event_ref(event);
3315+
3316+ memcpy(transform_, kIdentityTransform, sizeof(kIdentityTransform));
3317+ memcpy(cumulative_transform_, kIdentityTransform, sizeof(kIdentityTransform));
3318+ }
3319+
3320+ ~Private() {
3321+ frame_event_unref(event_);
3322+ }
3323+
3324+ const std::weak_ptr<Gesture> gesture_;
3325+ SharedGesture gesture_ref_;
3326+ const UFEvent event_;
3327+ UFFrame frame_;
3328+ TouchSet touches_;
3329+ uint64_t time_;
3330+ UGGestureState state_;
3331+ float original_center_x_;
3332+ float original_center_y_;
3333+ float original_radius_;
3334+ float original_angle_;
3335+ float radius_;
3336+ float angle_;
3337+ float transform_[3][3];
3338+ float cumulative_transform_[3][3];
3339+ float center_of_rotation_x_;
3340+ float center_of_rotation_y_;
3341+ UGGestureTypeMask recognized_;
3342+ bool touch_count_changed_;
3343+
3344+ void GetValues( const TouchSet & touches,
3345+ float * x,
3346+ float * y,
3347+ float * radius,
3348+ float* angle,
3349+ bool init
3350+ ) {
3351+ assert( x == NULL );
3352+ assert( y == NULL );
3353+ assert( radius == NULL );
3354+ assert( angle == NULL );
3355+
3356+ *x = 0;
3357+ *y = 0;
3358+
3359+ for (unsigned int touch_id : touches) {
3360+ UFTouch touch;
3361+ UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
3362+ if (status != UFStatusSuccess) {
3363+ fprintf(stderr, "Warning: failed to get touch from frame\n");
3364+ continue;
3365+ }
3366+
3367+ if (gesture_.lock()->recognizer().device_direct()) {
3368+ *x += frame_touch_get_window_x(touch);
3369+ *y += frame_touch_get_window_y(touch);
3370+ } else {
3371+ *x += frame_touch_get_device_x(touch);
3372+ *y += frame_touch_get_device_y(touch);
3373+ }
3374+ }
3375+
3376+ *x /= touches.size();
3377+ *y /= touches.size();
3378+
3379+ if (touches.size() == 1)
3380+ return;
3381+
3382+ *radius = 0;
3383+ *angle = 0;
3384+ int num_angles = 0;
3385+ for (unsigned int touch_id : touches) {
3386+ UFTouch touch;
3387+ float cur_x;
3388+ float cur_y;
3389+
3390+ UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
3391+ if (status != UFStatusSuccess) {
3392+ fprintf(stderr, "Warning: failed to get touch from frame\n");
3393+ continue;
3394+ }
3395+
3396+ if (gesture_.lock()->recognizer().device_direct()) {
3397+ cur_x = frame_touch_get_window_x(touch);
3398+ cur_y = frame_touch_get_window_y(touch);
3399+ } else {
3400+ cur_x = frame_touch_get_device_x(touch);
3401+ cur_y = frame_touch_get_device_y(touch);
3402+ }
3403+
3404+ *radius += sqrtf((cur_x - *x) * (cur_x - *x) + (cur_y - *y) * (cur_y - *y));
3405+
3406+ float new_angle = atan2f(cur_y - *y, cur_x - *x);
3407+
3408+ if (init) {
3409+ *angle += new_angle;
3410+ num_angles++;
3411+ } else if (frame_touch_get_state(touch) != UFTouchStateBegin) {
3412+ float prev_angle = gesture_.lock()->AngleForTouch(touch_id);
3413+
3414+ if (new_angle - prev_angle < -M_PI)
3415+ new_angle += 2 * M_PI;
3416+ else if (new_angle - prev_angle > M_PI)
3417+ new_angle -= 2 * M_PI;
3418+
3419+ *angle += new_angle - prev_angle;
3420+ num_angles++;
3421+ }
3422+
3423+ gesture_.lock()->SetAngleForTouch(touch_id, new_angle);
3424+ }
3425+
3426+ *radius /= touches.size();
3427+ *angle /= num_angles;
3428+ if (!init)
3429+ *angle += angle_;
3430+ }
3431+
3432+ /**
3433+ * Determine the center of rotation point.
3434+ *
3435+ * For any given point q that is transformed by a 2D affine transformation
3436+ * matrix T about anchor point P the new point q' may be determined by the
3437+ * following equation:
3438+ *
3439+ * q' = T * (q - P) + P
3440+ *
3441+ * T and P are dependent, so we can modify one and find a new value for the
3442+ * other. We will label the original T and P as T0 and P0, and the new values
3443+ * will be labeled T1 and P1. We can find new values by solving the following
3444+ * equation:
3445+ *
3446+ * q' = T0 * (q - P0) + P0 = T1 * (q - P1) + P1
3447+ *
3448+ * In the calculations below, we use variables for the scalar values
3449+ * that make up T0, P0, T1, and P1:
3450+ *
3451+ * T0: [ a -b c ] P0: [ x0 ] T1: [ a -b 0 ] P1: [ x1 ]
3452+ * [ b a d ] [ y0 ] [ b a 0 ] [ y1 ]
3453+ * [ 0 0 1 ] [ 0 ] [ 0 0 1 ] [ 0 ]
3454+ *
3455+ * Note that rotation and scaling are independent of the anchor point, so a and
3456+ * b are equivalent between the transformation matrices.
3457+ *
3458+ * Since we know all the values of T0, P0, and T1, we can calculate the values
3459+ * x1 and y1 in P1.
3460+ */
3461+ void SetCenterOfRotation() {
3462+ float a = transform_[0][0];
3463+ float b = transform_[1][0];
3464+ float c = transform_[0][2];
3465+ float d = transform_[0][2];
3466+ float x0 = original_center_x_ + cumulative_transform_[0][2];
3467+ float y0 = original_center_y_ + cumulative_transform_[1][2];
3468+ float x1;
3469+ float y1;
3470+
3471+ float div = a*a - 2*a + b*b + 1;
3472+
3473+ // TODO: Replace magic number here :-)
3474+ if( ::fabsf( div ) < 1e-5 )
3475+ return;
3476+
3477+ x1 = (a*a*x0 - a*(2*x0+c) + b*b*x0 - b*d + c + x0) / div;
3478+ y1 = (a*a*y0 - a*(2*y0+d) + b*b*y0 + b*c + d + y0) / div;
3479+
3480+ center_of_rotation_x_ = x1;
3481+ center_of_rotation_y_ = y1;
3482+ }
3483+
3484+ void CheckGestureEnd() {
3485+ std::size_t num_active_touches = 0;
3486+
3487+ for (unsigned int touch_id : touches_) {
3488+ UFTouch touch;
3489+ UFStatus status = frame_frame_get_touch_by_id(frame_, &touch_id, &touch);
3490+ if (status != UFStatusSuccess) {
3491+ fprintf(stderr, "Warning: failed to get touch from frame by id\n");
3492+ continue;
3493+ }
3494+
3495+ if (frame_touch_get_state(touch) == UFTouchStateEnd) {
3496+ continue;
3497+ } else {
3498+ int pending_end;
3499+ status = frame_touch_get_property(touch, UFTouchPropertyPendingEnd,
3500+ &pending_end);
3501+ if (status != UFStatusSuccess) {
3502+ fprintf(stderr, "Warning: failed to get touch pending end property\n");
3503+ continue;
3504+ }
3505+
3506+ if (pending_end)
3507+ continue;
3508+ }
3509+
3510+ num_active_touches++;
3511+ }
3512+
3513+ const UGSubscription * subscription = gesture_.lock()->subscription();
3514+ unsigned int touches_start = subscription->touches_start();
3515+ unsigned int touches_min = subscription->touches_min();
3516+ if ((!touches_min && num_active_touches < touches_start) ||
3517+ (touches_min && num_active_touches < touches_min))
3518+ state_ = UGGestureStateEnd;
3519+ }
3520+
3521+ void SetTransforms() {
3522+ float center_x;
3523+ float center_y;
3524+ float new_radius = radius_;
3525+ float new_angle = angle_;
3526+ GetValues( touches_, &center_x, &center_y, &new_radius, &new_angle, false);
3527+
3528+ if (touch_count_changed_) {
3529+ float scale = radius_ > 0 ? new_radius / radius_ : 1;
3530+
3531+ transform_[0][0] = cosf(new_angle - angle_) * scale;
3532+ transform_[0][1] = -sinf(new_angle - angle_) * scale;
3533+ transform_[0][2] =
3534+ center_x - cumulative_transform_[0][2] - original_center_x_;
3535+ transform_[1][0] = -transform_[0][1];
3536+ transform_[1][1] = transform_[0][0];
3537+ transform_[1][2] =
3538+ center_y - cumulative_transform_[1][2] - original_center_y_;
3539+
3540+ scale = original_radius_ > 0 ? new_radius / original_radius_ : 1;
3541+
3542+ cumulative_transform_[0][0] = ::cosf( new_angle - original_angle_ ) * scale;
3543+ cumulative_transform_[0][1] = -::sinf( new_angle - original_angle_ ) * scale;
3544+ cumulative_transform_[0][2] = center_x - original_center_x_;
3545+ cumulative_transform_[1][0] = -cumulative_transform_[0][1];
3546+ cumulative_transform_[1][1] = cumulative_transform_[0][0];
3547+ cumulative_transform_[1][2] = center_y - original_center_y_;
3548+ } else {
3549+ original_radius_ += new_radius - radius_;
3550+ original_angle_ += new_angle - angle_;
3551+ original_center_x_ +=
3552+ center_x - (original_center_x_ + cumulative_transform_[0][2]);
3553+ original_center_y_ +=
3554+ center_y - (original_center_y_ + cumulative_transform_[1][2]);
3555+ }
3556+
3557+ radius_ = new_radius;
3558+ angle_ = new_angle;
3559+ }
3560+
3561+ uint64_t CumulativeTime() const {
3562+ return( time_ - gesture_.lock()->start_time() );
3563+ }
3564+
3565+ float CumulativeDrag2() const {
3566+ float res_x = gesture_.lock()->recognizer().device_x_res();
3567+ float res_y = gesture_.lock()->recognizer().device_y_res();
3568+
3569+ return fabsf(cumulative_transform_[0][2] / res_x *
3570+ cumulative_transform_[0][2] / res_x +
3571+ cumulative_transform_[1][2] / res_y *
3572+ cumulative_transform_[1][2] / res_y);
3573+ }
3574+
3575+ float CumulativePinch() const {
3576+ float pinch = original_radius_ > 0 ? radius_ / original_radius_ : 1;
3577+
3578+ return( pinch < 1 ? 1 / pinch : pinch );
3579+ }
3580+ };
3581+
3582+
3583+
3584+ UGSlice::UGSlice( const SharedGesture & gesture,
3585+ UFEvent event,
3586+ const TouchSet & touches,
3587+ UGGestureTypeMask recognized)
3588+ : d_( new Private( gesture, event, touches, recognized ) ) {
3589+
3590+ }
3591+
3592+ UGSlice::UGSlice( const SharedUGSlice & prev,
3593+ UFEvent event,
3594+ const TouchSet& touches )
3595+ : d_( new Private( prev, event, touches ) ) {
3596+ }
3597+
3598+ UGSlice* UGSlice::NewUGSlice( const SharedGesture & gesture,
3599+ UFEvent event,
3600+ const TouchSet & touches,
3601+ UGGestureTypeMask recognized ) {
3602+
3603+ UGSlice* slice = new UGSlice(gesture, event, touches, recognized);
3604+
3605+ UFStatus status = frame_event_get_property( event,
3606+ UFEventPropertyFrame,
3607+ &slice->d_->frame_);
3608+ if (status != UFStatusSuccess) {
3609+ fprintf(stderr, "Warning: failed to get frame from event\n");
3610+ delete slice;
3611+ return NULL;
3612+ }
3613+
3614+ slice->d_->GetValues( touches,
3615+ &slice->d_->original_center_x_,
3616+ &slice->d_->original_center_y_,
3617+ &slice->d_->original_radius_,
3618+ &slice->d_->original_angle_,
3619+ true);
3620+
3621+ slice->d_->radius_ = slice->d_->original_radius_;
3622+ slice->d_->angle_ = slice->d_->original_angle_;
3623+
3624+ return slice;
3625+ }
3626+
3627+ UGSlice* UGSlice::NewUGSlice(const SharedUGSlice& prev, UFEvent event,
3628+ const TouchSet& touches) {
3629+ UGSlice* slice = new UGSlice(prev, event, touches);
3630+
3631+ UFStatus status = frame_event_get_property( event,
3632+ UFEventPropertyFrame,
3633+ &slice->d_->frame_ );
3634+ if (status != UFStatusSuccess) {
3635+ fprintf(stderr, "Warning: failed to get frame from event\n");
3636+ delete slice;
3637+ return NULL;
3638+ }
3639+
3640+ if (slice->d_->touch_count_changed_) {
3641+ slice->d_->GetValues( touches,
3642+ &slice->d_->original_center_x_,
3643+ &slice->d_->original_center_y_,
3644+ &slice->d_->original_radius_,
3645+ &slice->d_->original_angle_,
3646+ true);
3647+ slice->d_->radius_ = slice->d_->original_radius_;
3648+ slice->d_->angle_ = slice->d_->original_angle_;
3649+ } else {
3650+ slice->d_->SetTransforms();
3651+ slice->d_->SetCenterOfRotation();
3652+ slice->d_->CheckGestureEnd();
3653+ }
3654+
3655+ return slice;
3656+ }
3657+
3658+ UGGestureTypeMask UGSlice::CheckRecognition( const UGSubscription & subscription ) {
3659+ if ((subscription.mask() & UGGestureTypeDrag ) &&
3660+ (!subscription.drag().timeout_ ||
3661+ d_->CumulativeTime() < subscription.drag().timeout_) &&
3662+ d_->CumulativeDrag2() > subscription.drag().threshold_)
3663+ d_->recognized_ |= UGGestureTypeDrag;
3664+
3665+ if ((subscription.mask() & UGGestureTypePinch) &&
3666+ (!subscription.pinch().timeout_ ||
3667+ d_->CumulativeTime() < subscription.pinch().timeout_) &&
3668+ d_->CumulativePinch() > subscription.pinch().threshold_)
3669+ d_->recognized_ |= UGGestureTypePinch;
3670+
3671+ if ((subscription.mask() & UGGestureTypeRotate) &&
3672+ (!subscription.rotate().timeout_ ||
3673+ d_->CumulativeTime() < subscription.rotate().timeout_) &&
3674+ ::fabsf( d_->angle_ - d_->original_angle_) > subscription.rotate().threshold_)
3675+ d_->recognized_ |= UGGestureTypeRotate;
3676+
3677+ if ((subscription.mask() & UGGestureTypeTap) &&
3678+ d_->CumulativeTime() < subscription.tap().timeout_ &&
3679+ d_->state_ == UGGestureStateEnd)
3680+ d_->recognized_ |= UGGestureTypeTap;
3681+
3682+ if (subscription.mask() & UGGestureTypeTouch)
3683+ d_->recognized_ |= UGGestureTypeTouch;
3684+
3685+ return( d_->recognized_ );
3686+ }
3687+
3688+ // Might be a performance penalty.
3689+ UGStatus UGSlice::GetTouchId(unsigned int index, void* touch_id) const {
3690+
3691+ assert( touch_id == NULL );
3692+
3693+ auto it = d_->touches_.begin();
3694+ for( unsigned int i = 0; i < index; ++i, ++it )
3695+ if( it == d_->touches_.end() )
3696+ return UGStatusErrorInvalidIndex;
3697+
3698+ *reinterpret_cast<unsigned int*>( touch_id ) = *it;
3699+ return( UGStatusSuccess );
3700+ }
3701+
3702+ UGStatus UGSlice::GetProperty(UGSliceProperty property, void* value) const {
3703+ assert( value == NULL );
3704+ switch( property ) {
3705+ case UGSlicePropertyId:
3706+ *reinterpret_cast<unsigned int*>(value) = d_->gesture_.lock()->id();
3707+ return UGStatusSuccess;
3708+
3709+ case UGSlicePropertyState:
3710+ *reinterpret_cast<UGGestureState*>( value ) = d_->state_;
3711+ return UGStatusSuccess;
3712+
3713+ case UGSlicePropertySubscription:
3714+ *reinterpret_cast<void**>( value ) = d_->gesture_.lock()->subscription();
3715+ return UGStatusSuccess;
3716+
3717+ case UGSlicePropertyRecognized:
3718+ *reinterpret_cast<UGGestureTypeMask*>(value) = d_->recognized_;
3719+ return UGStatusSuccess;
3720+
3721+ case UGSlicePropertyNumTouches:
3722+ *reinterpret_cast<unsigned int*>(value) = d_->touches_.size();
3723+ return UGStatusSuccess;
3724+
3725+ case UGSlicePropertyFrame:
3726+ *reinterpret_cast<UFFrame*>(value) = d_->frame_;
3727+ return UGStatusSuccess;
3728+
3729+ case UGSlicePropertyOriginalCenterX:
3730+ *reinterpret_cast<float*>(value) = d_->original_center_x_;
3731+ return UGStatusSuccess;
3732+
3733+ case UGSlicePropertyOriginalCenterY:
3734+ *reinterpret_cast<float*>(value) = d_->original_center_y_;
3735+ return UGStatusSuccess;
3736+
3737+ case UGSlicePropertyOriginalRadius:
3738+ *reinterpret_cast<float*>(value) = d_->original_radius_;
3739+ return UGStatusSuccess;
3740+
3741+ case UGSlicePropertyTransform:
3742+ *reinterpret_cast<UGTransform**>(value) = &d_->transform_;
3743+ return UGStatusSuccess;
3744+
3745+ case UGSlicePropertyCumulativeTransform:
3746+ *reinterpret_cast<UGTransform**>(value) = &d_->cumulative_transform_;
3747+ return UGStatusSuccess;
3748+
3749+ case UGSlicePropertyCenterOfRotationX:
3750+ *reinterpret_cast<float*>(value) = d_->center_of_rotation_x_;
3751+ return UGStatusSuccess;
3752+
3753+ case UGSlicePropertyCenterOfRotationY:
3754+ *reinterpret_cast<float*>(value) = d_->center_of_rotation_y_;
3755+ return UGStatusSuccess;
3756+ default:
3757+ break;
3758+ }
3759+
3760+ return UGStatusErrorUnknownProperty;
3761+ }
3762+
3763+ void UGSlice::ReferenceGesture() {
3764+ d_->gesture_ref_ = d_->gesture_.lock();
3765+ }
3766+
3767+ uint64_t UGSlice::time() const {
3768+ return d_->time_;
3769+ }
3770+
3771+ const TouchSet & UGSlice::touches() {
3772+ return d_->touches_;
3773+ }
3774+
3775+ const UFFrame & UGSlice::frame() {
3776+ return d_->frame_;
3777+ }
3778+
3779+ UGGestureState UGSlice::state() const {
3780+ return d_->state_;
3781+ }
3782+
3783+ void UGSlice::set_state( UGGestureState state ) {
3784+ d_->state_ = state;
3785+ }
3786+
3787+ }
3788+ // extern "C" {
3789+
3790+ UGStatus grail_slice_get_property( const UGSlice slice,
3791+ UGSliceProperty property,
3792+ void* value) {
3793+ if( slice == NULL )
3794+ return( UGStatusErrorGeneric );
3795+
3796+ return static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(property, value);
3797+ }
3798+
3799+ unsigned int grail_slice_get_id(const UGSlice slice) {
3800+ if( slice == NULL )
3801+ return( UGStatusErrorGeneric );
3802+ unsigned int id;
3803+ UGStatus status = static_cast< const utouch::grail::UGSlice*>( slice )->GetProperty(UGSlicePropertyId, &id);
3804+ assert(status == UGStatusSuccess);
3805+ return id;
3806+ }
3807+
3808+ UGGestureState grail_slice_get_state(const UGSlice slice) {
3809+ assert( slice == NULL );
3810+ UGGestureState state;
3811+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyState, &state);
3812+ assert(status == UGStatusSuccess);
3813+ return state;
3814+ }
3815+
3816+ UGGestureTypeMask grail_slice_get_recognized(const UGSlice slice) {
3817+ if( slice == NULL )
3818+ return( UGStatusErrorGeneric );
3819+
3820+ UGGestureTypeMask mask;
3821+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyRecognized, &mask);
3822+ assert(status == UGStatusSuccess);
3823+ return mask;
3824+ }
3825+
3826+ UGSubscription grail_slice_get_subscription(const UGSlice slice) {
3827+ assert( slice == NULL );
3828+
3829+ UGSubscription subscription;
3830+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertySubscription,
3831+ &subscription);
3832+ assert(status == UGStatusSuccess);
3833+ return subscription;
3834+ }
3835+
3836+ unsigned int grail_slice_get_num_touches(const UGSlice slice) {
3837+ assert( slice == NULL );
3838+
3839+ unsigned int num_touches;
3840+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyNumTouches, &num_touches);
3841+ assert(status == UGStatusSuccess);
3842+ return num_touches;
3843+ }
3844+
3845+ UGStatus grail_slice_get_touch_id(const UGSlice slice, unsigned int index,
3846+ void *touch_id) {
3847+ if( slice == NULL )
3848+ return( UGStatusErrorGeneric );
3849+ return static_cast< const utouch::grail::UGSlice* >( slice )->GetTouchId(index, touch_id);
3850+ }
3851+
3852+ float grail_slice_get_original_center_x(const UGSlice slice) {
3853+ if( slice == NULL )
3854+ return( UGStatusErrorGeneric );
3855+ float x;
3856+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalCenterX, &x);
3857+ assert(status == UGStatusSuccess);
3858+ return x;
3859+ }
3860+
3861+ float grail_slice_get_original_center_y(const UGSlice slice) {
3862+ if( slice == NULL )
3863+ return( UGStatusErrorGeneric );
3864+ float y;
3865+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalCenterY, &y);
3866+ assert(status == UGStatusSuccess);
3867+ return y;
3868+ }
3869+
3870+ float grail_slice_get_original_radius(const UGSlice slice) {
3871+ if( slice == NULL )
3872+ return( UGStatusErrorGeneric );
3873+ float radius;
3874+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyOriginalRadius, &radius);
3875+ assert(status == UGStatusSuccess);
3876+ return radius;
3877+ }
3878+
3879+ float grail_slice_get_center_of_rotation_x(const UGSlice slice) {
3880+ if( slice == NULL )
3881+ return( UGStatusErrorGeneric );
3882+ float x;
3883+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCenterOfRotationX, &x);
3884+ assert(status == UGStatusSuccess);
3885+ return x;
3886+ }
3887+
3888+ float grail_slice_get_center_of_rotation_y(const UGSlice slice) {
3889+ if( slice == NULL )
3890+ return( UGStatusErrorGeneric );
3891+ float y;
3892+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCenterOfRotationY, &y);
3893+ assert(status == UGStatusSuccess);
3894+ return y;
3895+ }
3896+
3897+ const UGTransform *grail_slice_get_transform(const UGSlice slice) {
3898+ assert( slice == NULL );
3899+
3900+ UGTransform *transform;
3901+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyTransform, &transform);
3902+ assert(status == UGStatusSuccess);
3903+ return transform;
3904+ }
3905+
3906+ const UGTransform *grail_slice_get_cumulative_transform(const UGSlice slice) {
3907+ assert( slice == NULL );
3908+
3909+ UGTransform *transform;
3910+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyCumulativeTransform,
3911+ &transform);
3912+ assert(status == UGStatusSuccess);
3913+ return transform;
3914+ }
3915+
3916+ const UFFrame grail_slice_get_frame(const UGSlice slice) {
3917+ assert( slice == NULL );
3918+
3919+ UFFrame frame;
3920+ UGStatus status = static_cast< const utouch::grail::UGSlice* >( slice )->GetProperty(UGSlicePropertyFrame, &frame);
3921+ assert(status == UGStatusSuccess);
3922+ return frame;
3923+ }
3924+}
3925+// } // extern "C"
3926
3927=== modified file 'src/v3/slice.h'
3928--- src/v3/slice.h 2011-10-20 23:55:57 +0000
3929+++ src/v3/slice.h 2011-11-01 21:20:40 +0000
3930@@ -27,69 +27,61 @@
3931
3932 #include "utouch/grail.h"
3933
3934-class Gesture;
3935-
3936-typedef std::shared_ptr<Gesture> SharedGesture;
3937-typedef std::shared_ptr<UGSlice_> SharedUGSlice_;
3938-typedef std::set<unsigned int> TouchSet;
3939-
3940-class UGSlice_ {
3941- public:
3942- static UGSlice_* NewUGSlice_(const SharedGesture& gesture, UFEvent event,
3943- const TouchSet& touches,
3944- UGGestureTypeMask recognized);
3945- static UGSlice_* NewUGSlice_(const SharedUGSlice_& prev, UFEvent event,
3946- const TouchSet& touches);
3947-
3948- ~UGSlice_();
3949-
3950- void CheckGestureEnd();
3951- UGGestureTypeMask CheckRecognition(const UGSubscription_& subscription);
3952- UGStatus GetTouchId(unsigned int index, void* touch_id) const;
3953- UGStatus GetProperty(UGSliceProperty property, void* value) const;
3954- void ReferenceGesture() { gesture_ref_ = gesture_.lock(); }
3955-
3956- uint64_t time() const { return time_; }
3957- const TouchSet& touches() { return touches_; }
3958- const UFFrame& frame() { return frame_; }
3959- UGGestureState state() const { return state_; }
3960- void set_state(UGGestureState state) { state_ = state; }
3961-
3962- UGSlice_(const UGSlice_&) = delete;
3963- void operator=(const UGSlice_&) = delete;
3964-
3965- private:
3966- const std::weak_ptr<Gesture> gesture_;
3967- SharedGesture gesture_ref_;
3968- const UFEvent event_;
3969- UFFrame frame_;
3970- TouchSet touches_;
3971- uint64_t time_;
3972- UGGestureState state_;
3973- float original_center_x_;
3974- float original_center_y_;
3975- float original_radius_;
3976- float original_angle_;
3977- float radius_;
3978- float angle_;
3979- float transform_[3][3];
3980- float cumulative_transform_[3][3];
3981- float center_of_rotation_x_;
3982- float center_of_rotation_y_;
3983- UGGestureTypeMask recognized_;
3984- bool touch_count_changed_;
3985-
3986- UGSlice_(const SharedGesture& gesture, UFEvent event, const TouchSet& touches,
3987- UGGestureTypeMask recognized);
3988- UGSlice_(const SharedUGSlice_& prev, UFEvent event, const TouchSet& touches);
3989-
3990- void GetValues(const TouchSet& touches, float* x, float* y, float* radius,
3991- float* angle, bool init);
3992- void SetTransforms();
3993- void SetCenterOfRotation();
3994- uint64_t CumulativeTime() const;
3995- float CumulativeDrag2() const;
3996- float CumulativePinch() const;
3997-};
3998-
3999+namespace utouch {
4000+ namespace grail {
4001+
4002+ class Gesture;
4003+
4004+ class UGSlice;
4005+ class UGSubscription;
4006+
4007+ typedef std::shared_ptr<Gesture> SharedGesture;
4008+ typedef std::shared_ptr<UGSlice> SharedUGSlice;
4009+ typedef std::set<unsigned int> TouchSet;
4010+
4011+ class UGSlice {
4012+ public:
4013+
4014+ static UGSlice* NewUGSlice(const SharedGesture& gesture, UFEvent event,
4015+ const TouchSet& touches,
4016+ UGGestureTypeMask recognized);
4017+ static UGSlice* NewUGSlice(const SharedUGSlice& prev, UFEvent event,
4018+ const TouchSet& touches);
4019+
4020+ void CheckGestureEnd();
4021+
4022+ UGGestureTypeMask CheckRecognition( const UGSubscription & subscription );
4023+
4024+ UGStatus GetTouchId(unsigned int index, void* touch_id) const;
4025+
4026+ UGStatus GetProperty(UGSliceProperty property, void* value) const;
4027+
4028+ void ReferenceGesture();
4029+
4030+ uint64_t time() const;
4031+ const TouchSet& touches();
4032+ const UFFrame& frame();
4033+ UGGestureState state() const;
4034+ void set_state( UGGestureState state );
4035+
4036+ // Disable compiler generated c'tor, copy c'tor and assignment operator.
4037+ UGSlice( const UGSlice & ) = delete;
4038+ // void operator=( const UGSlice & ) = delete;
4039+ bool operator==( const UGSlice & ) const = delete;
4040+
4041+ protected:
4042+ struct Private;
4043+ std::shared_ptr< Private > d_;
4044+
4045+ UGSlice( const SharedGesture & gesture,
4046+ UFEvent event,
4047+ const TouchSet & touches,
4048+ UGGestureTypeMask recognized);
4049+
4050+ UGSlice( const SharedUGSlice & prev,
4051+ UFEvent event,
4052+ const TouchSet& touches );
4053+ };
4054+ }
4055+}
4056 #endif // UTOUCH_GRAIL_SLICE_H_
4057
4058=== modified file 'src/v3/subscription.cpp'
4059--- src/v3/subscription.cpp 2011-10-20 16:00:48 +0000
4060+++ src/v3/subscription.cpp 2011-11-01 21:20:40 +0000
4061@@ -21,265 +21,303 @@
4062
4063 #include "v3/subscription.h"
4064
4065-#include <math.h>
4066-
4067-Limit::Limit(UGGestureType type) {
4068- switch (type) {
4069- case UGGestureTypeDrag:
4070- timeout_ = 300;
4071- threshold_ = 2.6;
4072- break;
4073-
4074- case UGGestureTypePinch:
4075- timeout_ = 300;
4076- threshold_ = 1.1; /* Different from grail v1, ratio instead of delta */
4077- break;
4078-
4079- case UGGestureTypeRotate:
4080- timeout_ = 500;
4081- threshold_ = 2 * M_PI / 50;
4082- break;
4083-
4084- case UGGestureTypeTap:
4085- timeout_ = 300;
4086- threshold_ = 0;
4087- break;
4088-
4089- case UGGestureTypeTouch:
4090- timeout_ = 0;
4091- threshold_ = 0;
4092- break;
4093- }
4094-}
4095-
4096-UGSubscription_::UGSubscription_()
4097- : device_(0),
4098- window_(0),
4099- mask_(0),
4100- touches_start_(2),
4101- touches_min_(0),
4102- touches_max_(0),
4103- drag_(UGGestureTypeDrag),
4104- pinch_(UGGestureTypePinch),
4105- rotate_(UGGestureTypeRotate),
4106- tap_(UGGestureTypeTap) {
4107-}
4108-
4109-bool UGSubscription_::IsValid() const {
4110- if (!device_ ||
4111- !window_ ||
4112- mask_ == 0 ||
4113- (touches_max_ && touches_start_ > touches_max_) ||
4114- (touches_min_ && touches_start_ < touches_min_))
4115- return false;
4116-
4117- return true;
4118-}
4119-
4120-UGStatus UGSubscription_::SetProperty(UGSubscriptionProperty property,
4121- const void* value) {
4122- switch (property) {
4123- case UGSubscriptionPropertyDevice: {
4124- UFDevice device = *reinterpret_cast<const UFDevice*>(value);
4125- if (!device)
4126- return UGStatusErrorInvalidValue;
4127- device_ = device;
4128- return UGStatusSuccess;
4129- }
4130-
4131- case UGSubscriptionPropertyWindow: {
4132- Window window = *reinterpret_cast<const Window*>(value);
4133- if (!window)
4134- return UGStatusErrorInvalidValue;
4135- window_ = window;
4136- return UGStatusSuccess;
4137- }
4138-
4139- case UGSubscriptionPropertyMask: {
4140- UGGestureTypeMask mask =
4141- *reinterpret_cast<const UGGestureTypeMask*>(value);
4142- if (mask == 0)
4143- return UGStatusErrorInvalidValue;
4144- mask_ = mask;
4145- return UGStatusSuccess;
4146- }
4147-
4148- case UGSubscriptionPropertyTouchesStart: {
4149- unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
4150- if (touches == 0 || touches > 5)
4151- return UGStatusErrorInvalidValue;
4152- touches_start_ = touches;
4153- return UGStatusSuccess;
4154- }
4155-
4156- case UGSubscriptionPropertyTouchesMinimum: {
4157- unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
4158- if (touches == 0 || touches > 5)
4159- return UGStatusErrorInvalidValue;
4160- touches_min_ = touches;
4161- return UGStatusSuccess;
4162- }
4163-
4164- case UGSubscriptionPropertyTouchesMaximum: {
4165- unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
4166- if (touches == 0 || touches > 5)
4167- return UGStatusErrorInvalidValue;
4168- touches_max_ = touches;
4169- return UGStatusSuccess;
4170- }
4171-
4172- case UGSubscriptionPropertyDragTimeout: {
4173- uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
4174- if (timeout < 0)
4175- return UGStatusErrorInvalidValue;
4176- drag_.set_timeout(timeout);
4177- return UGStatusSuccess;
4178- }
4179-
4180- case UGSubscriptionPropertyDragThreshold: {
4181- float threshold = *reinterpret_cast<const float*>(value);
4182- if (threshold < 0)
4183- return UGStatusErrorInvalidValue;
4184- drag_.set_threshold(threshold);
4185- return UGStatusSuccess;
4186- }
4187-
4188- case UGSubscriptionPropertyPinchTimeout: {
4189- uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
4190- if (timeout < 0)
4191- return UGStatusErrorInvalidValue;
4192- pinch_.set_timeout(timeout);
4193- return UGStatusSuccess;
4194- }
4195-
4196- case UGSubscriptionPropertyPinchThreshold: {
4197- float threshold = *reinterpret_cast<const float*>(value);
4198- if (threshold < 0)
4199- return UGStatusErrorInvalidValue;
4200- pinch_.set_threshold(threshold);
4201- return UGStatusSuccess;
4202- }
4203-
4204- case UGSubscriptionPropertyRotateTimeout: {
4205- uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
4206- if (timeout < 0)
4207- return UGStatusErrorInvalidValue;
4208- rotate_.set_timeout(timeout);
4209- return UGStatusSuccess;
4210- }
4211-
4212- case UGSubscriptionPropertyRotateThreshold: {
4213- float threshold = *reinterpret_cast<const float*>(value);
4214- if (threshold < 0)
4215- return UGStatusErrorInvalidValue;
4216- rotate_.set_threshold(threshold);
4217- return UGStatusSuccess;
4218- }
4219-
4220- case UGSubscriptionPropertyTapTimeout: {
4221- uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
4222- if (timeout < 0)
4223- return UGStatusErrorInvalidValue;
4224- tap_.set_timeout(timeout);
4225- return UGStatusSuccess;
4226- }
4227-
4228- case UGSubscriptionPropertyTapThreshold: {
4229- float threshold = *reinterpret_cast<const float*>(value);
4230- if (threshold < 0)
4231- return UGStatusErrorInvalidValue;
4232- tap_.set_threshold(threshold);
4233- return UGStatusSuccess;
4234- }
4235- }
4236-
4237- return UGStatusErrorUnknownProperty;
4238-}
4239-
4240-UGStatus UGSubscription_::GetProperty(UGSubscriptionProperty property,
4241- void* value) const {
4242- switch (property) {
4243- case UGSubscriptionPropertyDevice:
4244- *reinterpret_cast<UFDevice*>(value) = device_;
4245- return UGStatusSuccess;
4246-
4247- case UGSubscriptionPropertyWindow:
4248- *reinterpret_cast<Window*>(value) = window_;
4249- return UGStatusSuccess;
4250-
4251- case UGSubscriptionPropertyMask:
4252- *reinterpret_cast<UGGestureTypeMask*>(value) = mask_;
4253- return UGStatusSuccess;
4254-
4255- case UGSubscriptionPropertyTouchesStart:
4256- *reinterpret_cast<unsigned int*>(value) = touches_start_;
4257- return UGStatusSuccess;
4258-
4259- case UGSubscriptionPropertyTouchesMinimum:
4260- *reinterpret_cast<unsigned int*>(value) = touches_min_;
4261- return UGStatusSuccess;
4262-
4263- case UGSubscriptionPropertyTouchesMaximum:
4264- *reinterpret_cast<unsigned int*>(value) = touches_max_;
4265- return UGStatusSuccess;
4266-
4267- case UGSubscriptionPropertyDragTimeout:
4268- *reinterpret_cast<uint64_t*>(value) = drag_.timeout();
4269- return UGStatusSuccess;
4270-
4271- case UGSubscriptionPropertyDragThreshold:
4272- *reinterpret_cast<float*>(value) = drag_.threshold();
4273- return UGStatusSuccess;
4274-
4275- case UGSubscriptionPropertyPinchTimeout:
4276- *reinterpret_cast<uint64_t*>(value) = pinch_.timeout();
4277- return UGStatusSuccess;
4278-
4279- case UGSubscriptionPropertyPinchThreshold:
4280- *reinterpret_cast<float*>(value) = pinch_.threshold();
4281- return UGStatusSuccess;
4282-
4283- case UGSubscriptionPropertyRotateTimeout:
4284- *reinterpret_cast<uint64_t*>(value) = rotate_.timeout();
4285- return UGStatusSuccess;
4286-
4287- case UGSubscriptionPropertyRotateThreshold:
4288- *reinterpret_cast<float*>(value) = rotate_.threshold();
4289- return UGStatusSuccess;
4290-
4291- case UGSubscriptionPropertyTapTimeout:
4292- *reinterpret_cast<uint64_t*>(value) = tap_.timeout();
4293- return UGStatusSuccess;
4294-
4295- case UGSubscriptionPropertyTapThreshold:
4296- *reinterpret_cast<float*>(value) = tap_.threshold();
4297- return UGStatusSuccess;
4298- }
4299-
4300- return UGStatusErrorUnknownProperty;
4301-}
4302-
4303-extern "C" {
4304-
4305-UGStatus grail_subscription_new(UGSubscription* subscription) {
4306- *subscription = new UGSubscription_;
4307- return UGStatusSuccess;
4308+#include <cassert>
4309+#include <cmath>
4310+
4311+namespace utouch {
4312+ namespace grail {
4313+
4314+ UGSubscription::Limit::Limit(UGGestureType type) {
4315+ switch (type) {
4316+ case UGGestureTypeDrag:
4317+ timeout_ = 300;
4318+ threshold_ = 2.6;
4319+ break;
4320+
4321+ case UGGestureTypePinch:
4322+ timeout_ = 300;
4323+ threshold_ = 1.1; /* Different from grail v1, ratio instead of delta */
4324+ break;
4325+
4326+ case UGGestureTypeRotate:
4327+ timeout_ = 500;
4328+ threshold_ = 2 * M_PI / 50;
4329+ break;
4330+
4331+ case UGGestureTypeTap:
4332+ timeout_ = 300;
4333+ threshold_ = 0;
4334+ break;
4335+
4336+ case UGGestureTypeTouch:
4337+ timeout_ = 0;
4338+ threshold_ = 0;
4339+ break;
4340+ }
4341+ }
4342+
4343+ struct UGSubscription::Private {
4344+
4345+ Private() : device_(0),
4346+ window_(0),
4347+ mask_(0),
4348+ touches_start_(2),
4349+ touches_min_(0),
4350+ touches_max_(0),
4351+ drag_(UGGestureTypeDrag),
4352+ pinch_(UGGestureTypePinch),
4353+ rotate_(UGGestureTypeRotate),
4354+ tap_(UGGestureTypeTap) {
4355+ }
4356+
4357+ UFDevice device_;
4358+ Window window_;
4359+ UGGestureTypeMask mask_;
4360+ unsigned int touches_start_;
4361+ unsigned int touches_min_;
4362+ unsigned int touches_max_;
4363+ Limit drag_;
4364+ Limit pinch_;
4365+ Limit rotate_;
4366+ Limit tap_;
4367+ };
4368+
4369+ UGSubscription::UGSubscription()
4370+ : d_( new Private() ) {
4371+ }
4372+
4373+ bool UGSubscription::IsValid() const {
4374+ if (!d_->device_ ||
4375+ !d_->window_ ||
4376+ d_->mask_ == 0 ||
4377+ (d_->touches_max_ && d_->touches_start_ > d_->touches_max_) ||
4378+ (d_->touches_min_ && d_->touches_start_ < d_->touches_min_))
4379+ return false;
4380+
4381+ return true;
4382+ }
4383+
4384+ UGStatus UGSubscription::SetProperty(UGSubscriptionProperty property,
4385+ const void* value) {
4386+
4387+ assert( value == NULL );
4388+
4389+ switch (property) {
4390+ case UGSubscriptionPropertyDevice: {
4391+ UFDevice device = *reinterpret_cast<const UFDevice*>(value);
4392+ if (!device)
4393+ return UGStatusErrorInvalidValue;
4394+ d_->device_ = device;
4395+ return UGStatusSuccess;
4396+ }
4397+
4398+ case UGSubscriptionPropertyWindow: {
4399+ Window window = *reinterpret_cast<const Window*>(value);
4400+ if (!window)
4401+ return UGStatusErrorInvalidValue;
4402+ d_->window_ = window;
4403+ return UGStatusSuccess;
4404+ }
4405+
4406+ case UGSubscriptionPropertyMask: {
4407+ UGGestureTypeMask mask =
4408+ *reinterpret_cast<const UGGestureTypeMask*>(value);
4409+ if (mask == 0)
4410+ return UGStatusErrorInvalidValue;
4411+ d_->mask_ = mask;
4412+ return UGStatusSuccess;
4413+ }
4414+
4415+ case UGSubscriptionPropertyTouchesStart: {
4416+ unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
4417+ if (touches == 0 || touches > 5)
4418+ return UGStatusErrorInvalidValue;
4419+ d_->touches_start_ = touches;
4420+ return UGStatusSuccess;
4421+ }
4422+
4423+ case UGSubscriptionPropertyTouchesMinimum: {
4424+ unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
4425+ if (touches == 0 || touches > 5)
4426+ return UGStatusErrorInvalidValue;
4427+ d_->touches_min_ = touches;
4428+ return UGStatusSuccess;
4429+ }
4430+
4431+ case UGSubscriptionPropertyTouchesMaximum: {
4432+ unsigned int touches = *reinterpret_cast<const unsigned int*>(value);
4433+ if (touches == 0 || touches > 5)
4434+ return UGStatusErrorInvalidValue;
4435+ d_->touches_max_ = touches;
4436+ return UGStatusSuccess;
4437+ }
4438+
4439+ case UGSubscriptionPropertyDragTimeout: {
4440+ uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
4441+ if (timeout < 0)
4442+ return UGStatusErrorInvalidValue;
4443+ d_->drag_.timeout_ = timeout;
4444+ return UGStatusSuccess;
4445+ }
4446+
4447+ case UGSubscriptionPropertyDragThreshold: {
4448+ float threshold = *reinterpret_cast<const float*>(value);
4449+ if (threshold < 0)
4450+ return UGStatusErrorInvalidValue;
4451+ d_->drag_.threshold_ = threshold;
4452+ return UGStatusSuccess;
4453+ }
4454+
4455+ case UGSubscriptionPropertyPinchTimeout: {
4456+ uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
4457+ if (timeout < 0)
4458+ return UGStatusErrorInvalidValue;
4459+ d_->pinch_.timeout_ = timeout;
4460+ return UGStatusSuccess;
4461+ }
4462+
4463+ case UGSubscriptionPropertyPinchThreshold: {
4464+ float threshold = *reinterpret_cast<const float*>(value);
4465+ if (threshold < 0)
4466+ return UGStatusErrorInvalidValue;
4467+ d_->pinch_.threshold_ = threshold;
4468+ return UGStatusSuccess;
4469+ }
4470+
4471+ case UGSubscriptionPropertyRotateTimeout: {
4472+ uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
4473+ if (timeout < 0)
4474+ return UGStatusErrorInvalidValue;
4475+ d_->rotate_.timeout_ = timeout;
4476+ return UGStatusSuccess;
4477+ }
4478+
4479+ case UGSubscriptionPropertyRotateThreshold: {
4480+ float threshold = *reinterpret_cast<const float*>(value);
4481+ if (threshold < 0)
4482+ return UGStatusErrorInvalidValue;
4483+ d_->rotate_.threshold_ = threshold;
4484+ return UGStatusSuccess;
4485+ }
4486+
4487+ case UGSubscriptionPropertyTapTimeout: {
4488+ uint64_t timeout = *reinterpret_cast<const uint64_t*>(value);
4489+ if (timeout < 0)
4490+ return UGStatusErrorInvalidValue;
4491+ d_->tap_.timeout_ = timeout;
4492+ return UGStatusSuccess;
4493+ }
4494+
4495+ case UGSubscriptionPropertyTapThreshold: {
4496+ float threshold = *reinterpret_cast<const float*>(value);
4497+ if (threshold < 0)
4498+ return UGStatusErrorInvalidValue;
4499+ d_->tap_.threshold_ = threshold;
4500+ return UGStatusSuccess;
4501+ }
4502+ }
4503+
4504+ return UGStatusErrorUnknownProperty;
4505+ }
4506+
4507+ UGStatus UGSubscription::GetProperty(UGSubscriptionProperty property,
4508+ void* value) const {
4509+ assert( value == NULL );
4510+ switch (property) {
4511+ case UGSubscriptionPropertyDevice:
4512+ *reinterpret_cast<UFDevice*>(value) = d_->device_;
4513+ return UGStatusSuccess;
4514+
4515+ case UGSubscriptionPropertyWindow:
4516+ *reinterpret_cast<Window*>(value) = d_->window_;
4517+ return UGStatusSuccess;
4518+
4519+ case UGSubscriptionPropertyMask:
4520+ *reinterpret_cast<UGGestureTypeMask*>(value) = d_->mask_;
4521+ return UGStatusSuccess;
4522+
4523+ case UGSubscriptionPropertyTouchesStart:
4524+ *reinterpret_cast<unsigned int*>(value) = d_->touches_start_;
4525+ return UGStatusSuccess;
4526+
4527+ case UGSubscriptionPropertyTouchesMinimum:
4528+ *reinterpret_cast<unsigned int*>(value) = d_->touches_min_;
4529+ return UGStatusSuccess;
4530+
4531+ case UGSubscriptionPropertyTouchesMaximum:
4532+ *reinterpret_cast<unsigned int*>(value) = d_->touches_max_;
4533+ return UGStatusSuccess;
4534+
4535+ case UGSubscriptionPropertyDragTimeout:
4536+ *reinterpret_cast<uint64_t*>(value) = d_->drag_.timeout_;
4537+ return UGStatusSuccess;
4538+
4539+ case UGSubscriptionPropertyDragThreshold:
4540+ *reinterpret_cast<float*>(value) = d_->drag_.threshold_;
4541+ return UGStatusSuccess;
4542+
4543+ case UGSubscriptionPropertyPinchTimeout:
4544+ *reinterpret_cast<uint64_t*>(value) = d_->pinch_.timeout_;
4545+ return UGStatusSuccess;
4546+
4547+ case UGSubscriptionPropertyPinchThreshold:
4548+ *reinterpret_cast<float*>(value) = d_->pinch_.threshold_;
4549+ return UGStatusSuccess;
4550+
4551+ case UGSubscriptionPropertyRotateTimeout:
4552+ *reinterpret_cast<uint64_t*>(value) = d_->rotate_.timeout_;
4553+ return UGStatusSuccess;
4554+
4555+ case UGSubscriptionPropertyRotateThreshold:
4556+ *reinterpret_cast<float*>(value) = d_->rotate_.threshold_;
4557+ return UGStatusSuccess;
4558+
4559+ case UGSubscriptionPropertyTapTimeout:
4560+ *reinterpret_cast<uint64_t*>(value) = d_->tap_.timeout_;
4561+ return UGStatusSuccess;
4562+
4563+ case UGSubscriptionPropertyTapThreshold:
4564+ *reinterpret_cast<float*>(value) = d_->tap_.threshold_;
4565+ return UGStatusSuccess;
4566+ }
4567+
4568+ return UGStatusErrorUnknownProperty;
4569+ }
4570+
4571+ UFDevice UGSubscription::device() const { return d_->device_; }
4572+ Window UGSubscription::window() const { return d_->window_; }
4573+ UGGestureTypeMask UGSubscription::mask() const { return d_->mask_; }
4574+ unsigned int UGSubscription::touches_start() const { return d_->touches_start_; }
4575+ unsigned int UGSubscription::touches_min() const { return d_->touches_min_; }
4576+ unsigned int UGSubscription::touches_max() const { return d_->touches_max_; }
4577+
4578+ const UGSubscription::Limit & UGSubscription::drag() const { return d_->drag_; }
4579+ const UGSubscription::Limit & UGSubscription::pinch() const { return d_->pinch_; }
4580+ const UGSubscription::Limit & UGSubscription::rotate() const { return d_->rotate_; }
4581+ const UGSubscription::Limit & UGSubscription::tap() const { return d_->tap_; }
4582+ }
4583+}
4584+// extern "C" {
4585+
4586+UGStatus grail_subscription_new(UGSubscription * subscription) {
4587+ *subscription = new UGSubscription();
4588+ return UGStatusSuccess;
4589 }
4590
4591 void grail_subscription_delete(UGSubscription subscription) {
4592- delete subscription;
4593+ delete( static_cast< utouch::grail::UGSubscription* >( subscription ) );
4594 }
4595
4596-UGStatus grail_subscription_set_property(UGSubscription subscription,
4597- UGSubscriptionProperty property,
4598- const void* value) {
4599- return subscription->SetProperty(property, value);
4600+UGStatus grail_subscription_set_property( UGSubscription subscription,
4601+ UGSubscriptionProperty property,
4602+ const void* value) {
4603+ return( static_cast< utouch::grail::UGSubscription* >( subscription )->SetProperty(property, value ) );
4604 }
4605
4606 UGStatus grail_subscription_get_property(UGSubscription subscription,
4607 UGSubscriptionProperty property,
4608 void* value) {
4609- return subscription->GetProperty(property, value);
4610+ return( static_cast< utouch::grail::UGSubscription* >( subscription )->GetProperty(property, value) );
4611 }
4612
4613-} // extern "C"
4614+// } // extern "C"
4615
4616=== modified file 'src/v3/subscription.h'
4617--- src/v3/subscription.h 2011-10-12 23:36:27 +0000
4618+++ src/v3/subscription.h 2011-11-01 21:20:40 +0000
4619@@ -26,58 +26,47 @@
4620
4621 #include "utouch/grail.h"
4622
4623-class Limit {
4624- public:
4625- explicit Limit(UGGestureType type);
4626-
4627- uint64_t timeout() const { return timeout_; }
4628- float threshold() const { return threshold_; }
4629-
4630- Limit(const Limit&) = delete;
4631- void operator=(const Limit&) = delete;
4632-
4633- private:
4634- void set_timeout(uint64_t timeout) { timeout_ = timeout; }
4635- void set_threshold(float threshold) { threshold_ = threshold; }
4636- uint64_t timeout_;
4637- float threshold_;
4638-
4639- friend class UGSubscription_;
4640-};
4641-
4642-class UGSubscription_ {
4643- public:
4644- UGSubscription_();
4645-
4646- bool IsValid() const;
4647- UGStatus SetProperty(UGSubscriptionProperty property, const void* value);
4648- UGStatus GetProperty(UGSubscriptionProperty property, void* value) const;
4649-
4650- UFDevice device() const { return device_; }
4651- Window window() const { return window_; }
4652- UGGestureTypeMask mask() const { return mask_; }
4653- unsigned int touches_start() const { return touches_start_; }
4654- unsigned int touches_min() const { return touches_min_; }
4655- unsigned int touches_max() const { return touches_max_; }
4656- const Limit& drag() const { return drag_; }
4657- const Limit& pinch() const { return pinch_; }
4658- const Limit& rotate() const { return rotate_; }
4659- const Limit& tap() const { return tap_; }
4660-
4661- UGSubscription_(const UGSubscription_&) = delete;
4662- void operator=(const UGSubscription_&) = delete;
4663-
4664- private:
4665- UFDevice device_;
4666- Window window_;
4667- UGGestureTypeMask mask_;
4668- unsigned int touches_start_;
4669- unsigned int touches_min_;
4670- unsigned int touches_max_;
4671- Limit drag_;
4672- Limit pinch_;
4673- Limit rotate_;
4674- Limit tap_;
4675-};
4676-
4677+#include <memory>
4678+
4679+namespace utouch {
4680+ namespace grail {
4681+
4682+ class UGSubscription {
4683+ public:
4684+
4685+ struct Limit {
4686+ explicit Limit( UGGestureType type );
4687+
4688+ uint64_t timeout_;
4689+ float threshold_;
4690+ };
4691+
4692+ UGSubscription();
4693+
4694+ bool IsValid() const;
4695+
4696+ UGStatus SetProperty(UGSubscriptionProperty property, const void* value);
4697+ UGStatus GetProperty(UGSubscriptionProperty property, void* value) const;
4698+
4699+ UFDevice device() const;
4700+ Window window() const;
4701+ UGGestureTypeMask mask() const;
4702+ unsigned int touches_start() const;
4703+ unsigned int touches_min() const;
4704+ unsigned int touches_max() const;
4705+
4706+ const Limit & drag() const;
4707+ const Limit & pinch() const;
4708+ const Limit & rotate() const;
4709+ const Limit & tap() const;
4710+
4711+ UGSubscription(const UGSubscription & ) = delete;
4712+ UGSubscription & operator=(const UGSubscription & ) = delete;
4713+
4714+ protected:
4715+ struct Private;
4716+ std::shared_ptr< Private > d_;
4717+ };
4718+ }
4719+}
4720 #endif // UTOUCH_GRAIL_SUBSCRIPTION_H_

Subscribers

People subscribed via source and target branches

to all changes: