1 diff -Naur easystroke-0.5.5.1/actiondb.cc easystroke-0.5.5.1-3mod/actiondb.cc
2 --- easystroke-0.5.5.1/actiondb.cc 2011-08-16 10:11:40.000000000 +0200
3 +++ easystroke-0.5.5.1-3mod/actiondb.cc 2011-11-16 22:53:54.000000000 +0100
7 RStrokeInfo si = get_info(i->first);
8 + if (verbosity >=2) printf("Action compared: %s\n", si->name.c_str());
9 r->r.insert(pair<double, pair<std::string, RStroke> >
10 (score, pair<std::string, RStroke>(si->name, *j)));
11 if (score > r->score) {
12 diff -Naur easystroke-0.5.5.1/composite.cc easystroke-0.5.5.1-3mod/composite.cc
13 --- easystroke-0.5.5.1/composite.cc 2011-08-16 10:11:40.000000000 +0200
14 +++ easystroke-0.5.5.1-3mod/composite.cc 2011-11-16 00:30:04.000000000 +0100
16 #include <glibmm/i18n.h>
18 double red, green, blue, alpha, width;
19 -std::list<Trace::Point> points;
20 +// std::list<Trace::Point> points;
22 -Popup::Popup(int x1, int y1, int x2, int y2) : Gtk::Window(Gtk::WINDOW_POPUP), rect(x1, y1, x2-x1, y2-y1) {
23 +Popup::Popup(Composite *comp, int x1, int y1, int x2, int y2) : Gtk::Window(Gtk::WINDOW_POPUP), rect(x1, y1, x2-x1, y2-y1) {
25 throw std::runtime_error(_("'composite' not available"));
28 Glib::RefPtr<Gdk::Colormap> colormap = get_screen()->get_rgba_colormap();
31 for (int i = 0; i < num_x; i++) {
32 pieces[i] = new Popup*[num_y];
33 for (int j = 0; j < num_y; j++)
34 - pieces[i][j] = new Popup(i*N,j*N,MIN((i+1)*N,w),MIN((j+1)*N,h));
35 + pieces[i][j] = new Popup(this,i*N,j*N,MIN((i+1)*N,w),MIN((j+1)*N,h));
42 void Popup::draw_line(Cairo::RefPtr<Cairo::Context> ctx) {
44 + if (!composite->points.size())
46 - std::list<Trace::Point>::iterator i = points.begin();
47 + std::list<Trace::Point>::iterator i = composite->points.begin();
48 ctx->move_to (i->x, i->y);
49 - for (; i != points.end(); i++)
50 + for (; i != composite->points.end(); i++)
51 ctx->line_to (i->x, i->y);
52 ctx->set_source_rgba((red+0.5)/2.0, (green+0.5)/2.0, (blue+0.5)/2.0, alpha/2.0);
53 ctx->set_line_width(width+1.0);
54 diff -Naur easystroke-0.5.5.1/composite.h easystroke-0.5.5.1-3mod/composite.h
55 --- easystroke-0.5.5.1/composite.h 2011-08-16 10:11:40.000000000 +0200
56 +++ easystroke-0.5.5.1-3mod/composite.h 2011-11-16 00:30:37.000000000 +0100
63 class Popup : public Gtk::Window {
64 bool on_expose(GdkEventExpose* event);
65 void draw_line(Cairo::RefPtr<Cairo::Context> ctx);
67 + Composite *composite;
69 - Popup(int x1, int y1, int x2, int y2);
70 + Popup(Composite *comp,int x1, int y1, int x2, int y2);
71 void invalidate(int x1, int y1, int x2, int y2);
75 virtual void start_();
78 + std::list<Trace::Point> points;
82 diff -Naur easystroke-0.5.5.1/debug.mk easystroke-0.5.5.1-3mod/debug.mk
83 --- easystroke-0.5.5.1/debug.mk 1970-01-01 01:00:00.000000000 +0100
84 +++ easystroke-0.5.5.1-3mod/debug.mk 2011-11-12 00:33:07.000000000 +0100
89 diff -Naur easystroke-0.5.5.1/debug.mk.ex easystroke-0.5.5.1-3mod/debug.mk.ex
90 --- easystroke-0.5.5.1/debug.mk.ex 2011-08-16 10:11:40.000000000 +0200
91 +++ easystroke-0.5.5.1-3mod/debug.mk.ex 1970-01-01 01:00:00.000000000 +0100
96 diff -Naur easystroke-0.5.5.1/gesture.cc easystroke-0.5.5.1-3mod/gesture.cc
97 --- easystroke-0.5.5.1/gesture.cc 2011-08-16 10:11:40.000000000 +0200
98 +++ easystroke-0.5.5.1-3mod/gesture.cc 2011-11-17 23:46:53.000000000 +0100
103 -Stroke::Stroke(PreStroke &ps, int trigger_, int button_, bool timeout_) : button(button_), timeout(timeout_) {
104 +Stroke::Stroke(PreStroke &ps, PreStroke &ps2, int trigger_, int button_, bool timeout_, int multi_finger_) : button(button_), timeout(timeout_), multi_finger(multi_finger_) {
105 trigger = (trigger_ == get_default_button()) ? 0 : trigger_;
107 + stroke_t *s = NULL;
109 - stroke_t *s = stroke_alloc(ps.size());
110 + s = stroke_alloc(ps.size());
111 for (std::vector<RTriple>::iterator i = ps.begin(); i != ps.end(); ++i)
112 stroke_add_point(s, (*i)->x, (*i)->y);
114 + stroke_t *s2 = NULL;
116 + s2 = stroke_alloc(ps2.size());
117 + for (std::vector<RTriple>::iterator i = ps2.begin(); i != ps2.end(); ++i)
118 + stroke_add_point(s2, (*i)->x, (*i)->y);
120 + stroke_normalize(s,s2);
123 stroke.reset(s, &stroke_free);
127 + stroke2.reset(s2, &stroke_free);
131 int Stroke::compare(RStroke a, RStroke b, double &score) {
134 if (a->button != b->button)
136 + if (a->multi_finger != b->multi_finger)
138 if (a->trigger != b->trigger) {
139 if (a->trigger && b->trigger)
145 - double cost = stroke_compare(a->stroke.get(), b->stroke.get(), NULL, NULL);
147 + if (a->multi_finger != 2) {
148 + cost = stroke_compare(a->stroke.get(), b->stroke.get(), NULL, NULL);
149 + if (verbosity >= 2) printf("compared cost=%g\n", cost);
151 + double how_compatible_1_1 = stroke_how_compatible( a->stroke.get(), b->stroke.get() );
152 + double how_compatible_2_2 = stroke_how_compatible( a->stroke2.get(), b->stroke2.get() );
153 + double how_compatible_1_2 = stroke_how_compatible( a->stroke.get(), b->stroke2.get() );
154 + double how_compatible_2_1 = stroke_how_compatible( a->stroke2.get(), b->stroke.get() );
155 + double how_compatible_e = ( how_compatible_1_1 + how_compatible_2_2 ) / 2.0;
156 + double how_compatible_r = ( how_compatible_1_2 + how_compatible_2_1 ) / 2.0;
157 + double how_compatible;
158 + bool compatible_e = (how_compatible_1_1 > 0.5 && how_compatible_2_2 > 0.5);
159 + bool compatible_r = (how_compatible_1_2 > 0.5 && how_compatible_2_1 > 0.5);
160 + stroke_t *stroke = NULL;
161 + stroke_t *stroke2 = NULL;
162 + if (! compatible_e && ! compatible_r) {
164 + } else if(compatible_e && ! compatible_r) {
165 + stroke = a->stroke.get();
166 + stroke2 = a->stroke2.get();
167 + how_compatible = how_compatible_e;
168 + } else if(! compatible_e && compatible_r) {
169 + stroke = a->stroke2.get();
170 + stroke2 = a->stroke.get();
171 + how_compatible = how_compatible_r;
172 + } else if( how_compatible_1_1 + how_compatible_2_2 >= how_compatible_1_2 + how_compatible_2_1) {
173 + stroke = a->stroke.get();
174 + stroke2 = a->stroke2.get();
175 + how_compatible = how_compatible_e;
177 + stroke = a->stroke2.get();
178 + stroke2 = a->stroke.get();
179 + how_compatible = how_compatible_r;
181 + double compatible_factor;
182 + double cost_1_1 = 0.0, cost_2_2 = 0.0;
183 + cost_1_1 = stroke_compare(stroke, b->stroke.get(), NULL, NULL);
184 + cost_2_2 = stroke_compare(stroke2, b->stroke2.get(), NULL, NULL);
185 + compatible_factor = 2.0 / ( 1.1 - how_compatible );
186 + cost = ( cost_1_1 + cost_2_2 ) / 2.0 * compatible_factor;
187 + if (verbosity >= 2) printf("compared cost=%g cost1_1=%g cost2_2=%g fact=%g\n", cost, cost_1_1, cost_2_2, compatible_factor);
189 + double diff_angle1 = stroke_radians_difference( stroke_orient_start(a->stroke.get(), a->stroke2.get()), stroke_orient_start(b->stroke.get(), b->stroke2.get()));
190 + double diff_angle2 = stroke_radians_difference( stroke_orient_middle(a->stroke.get(), a->stroke2.get()), stroke_orient_middle(b->stroke.get(), b->stroke2.get()));
191 + double diff_angle3 = stroke_radians_difference( stroke_orient_end(a->stroke.get(), a->stroke2.get()), stroke_orient_end(b->stroke.get(), b->stroke2.get()));
192 + double diff_angles = diff_angle1 + diff_angle2 + diff_angle3;
193 + double diff_dist1 = fabs(stroke_dist_start(a->stroke.get(), b->stroke.get()) - stroke_dist_start(a->stroke2.get(), b->stroke2.get()));
194 + double diff_dist2 = fabs(stroke_dist_middle(a->stroke.get(), b->stroke.get()) - stroke_dist_middle(a->stroke2.get(), b->stroke2.get()));
195 + double diff_dist3 = fabs(stroke_dist_end(a->stroke.get(), b->stroke.get()) - stroke_dist_end(a->stroke2.get(), b->stroke2.get()));
196 + double diff_dist = diff_dist1 + diff_dist2 + diff_dist3;
197 + double diff_dist1r = fabs(stroke_dist_start(a->stroke.get(), b->stroke2.get()) - stroke_dist_start(a->stroke2.get(), b->stroke.get()));
198 + double diff_dist2r = fabs(stroke_dist_middle(a->stroke.get(), b->stroke2.get()) - stroke_dist_middle(a->stroke2.get(), b->stroke.get()));
199 + double diff_dist3r = fabs(stroke_dist_end(a->stroke.get(), b->stroke2.get()) - stroke_dist_end(a->stroke2.get(), b->stroke.get()));
200 + double diff_distr = diff_dist1r + diff_dist2r + diff_dist3r;
201 + double cost_1 = 0.0, cost_2 = 0.0, cost_1_1 = 0.0, cost_1_2 = 0.0, cost_2_1 = 0.0, cost_2_2 = 0.0;
202 + if (verbosity >= 2) printf("compared dist=%g dist1=%g dist2=%g dist3=%g\n", diff_dist, diff_dist1, diff_dist2, diff_dist3);
203 + if (verbosity >= 2) printf("compared r dist=%g dist1=%g dist2=%g dist3=%g\n", diff_distr, diff_dist1r, diff_dist2r, diff_dist3r);
204 + if (diff_dist < diff_distr) {
205 + cost_1_1 = stroke_compare(a->stroke.get(), b->stroke.get(), NULL, NULL);
206 + cost_2_2 = stroke_compare(a->stroke2.get(), b->stroke2.get(), NULL, NULL);
207 + cost = ( cost_1_1 + cost_2_2 ) / 2.0;
208 + if (verbosity >= 2) printf("compared cost=%g cost1_1=%g cost2_2=%g\n", cost, cost_1_1, cost_2_2);
209 + if (cost_1_1 > stroke_infinity || cost_2_2 > stroke_infinity) return -1;
211 + cost_1_2 = stroke_compare(a->stroke.get(), b->stroke2.get(), NULL, NULL);
212 + cost_2_1 = stroke_compare(a->stroke2.get(), b->stroke.get(), NULL, NULL);
213 + cost = ( cost_1_2 + cost_2_1 ) / 2.0;
214 + if (verbosity >= 2) printf("compared cost=%g cost1_2=%g cost2_1=%g\n", cost, cost_1_2, cost_2_1);
215 + if (cost_1_2 > stroke_infinity || cost_2_1 > stroke_infinity) return -1;
217 + if (verbosity >= 2) printf("compared angle=%g angle1=%g angle2=%g angle3=%g\n", diff_angles, diff_angle1, diff_angle2, diff_angle3);
220 if (cost >= stroke_infinity)
222 score = MAX(1.0 - 2.5*cost, 0.0);
223 + if (verbosity >= 2) printf("score=%g\n", score);
229 RStroke Stroke::trefoil() {
233 for (int i = 0; i<=n; i++) {
234 double phi = M_PI*(-4.0*i/n)-2.7;
235 double r = exp(1.0 + sin(6.0*M_PI*i/n)) + 2.0;
236 s.add(create_triple(r*cos(phi), r*sin(phi), i));
238 - return Stroke::create(s, 0, 0, false);
239 + return Stroke::create(s, s2, 0, 0, false, 1);
241 diff -Naur easystroke-0.5.5.1/gesture.h easystroke-0.5.5.1-3mod/gesture.h
242 --- easystroke-0.5.5.1/gesture.h 2011-08-16 10:11:40.000000000 +0200
243 +++ easystroke-0.5.5.1-3mod/gesture.h 2011-11-15 23:08:23.000000000 +0100
246 int get_default_button();
248 +extern int verbosity;
257 - Stroke(PreStroke &s, int trigger_, int button_, bool timeout_);
258 + Stroke(PreStroke &s, PreStroke &s2, int trigger_, int button_, bool timeout_, int multi_finger_);
260 Glib::RefPtr<Gdk::Pixbuf> draw_(int size, double width = 2.0, bool inv = false) const;
261 mutable Glib::RefPtr<Gdk::Pixbuf> pb[2];
267 + std::vector<Point> ps2;
268 + for (unsigned int i = 0; i < size2(); i++)
269 + ps2.push_back(points2(i));
272 template<class Archive> void load(Archive & ar, const unsigned int version) {
273 std::vector<Point> ps;
275 + stroke_t *s = NULL;
277 - stroke_t *s = stroke_alloc(ps.size());
278 + s = stroke_alloc(ps.size());
279 for (std::vector<Point>::iterator i = ps.begin(); i != ps.end(); ++i)
280 stroke_add_point(s, i->x, i->y);
282 - stroke.reset(s, &stroke_free);
285 + stroke.reset(s, &stroke_free);
288 if (version == 0) return;
290 @@ -113,17 +123,39 @@
297 + std::vector<Point> ps2;
299 + stroke_t *s2 = NULL;
301 + s2 = stroke_alloc(ps2.size());
302 + for (std::vector<Point>::iterator i = ps2.begin(); i != ps2.end(); ++i)
303 + stroke_add_point(s2, i->x, i->y);
305 + stroke_normalize(s,s2);
308 + stroke.reset(s, &stroke_free);
312 + stroke2.reset(s2, &stroke_free);
321 boost::shared_ptr<stroke_t> stroke;
322 + boost::shared_ptr<stroke_t> stroke2;
324 - Stroke() : trigger(0), button(0), timeout(false) {}
325 - static RStroke create(PreStroke &s, int trigger_, int button_, bool timeout_) {
326 - return RStroke(new Stroke(s, trigger_, button_, timeout_));
327 + Stroke() : trigger(0), button(0), timeout(false), multi_finger(1) {}
328 + static RStroke create(PreStroke &s, PreStroke &s2, int trigger_, int button_, bool timeout_, int multi_finger_) {
329 + return RStroke(new Stroke(s, s2, trigger_, button_, timeout_, multi_finger_));
331 Glib::RefPtr<Gdk::Pixbuf> draw(int size, double width = 2.0, bool inv = false) const;
332 void draw(Cairo::RefPtr<Cairo::Surface> surface, int x, int y, int w, int h, double width = 2.0, bool inv = false) const;
334 bool trivial() const { return size() == 0 && button == 0; }
335 Point points(int n) const { Point p; stroke_get_point(stroke.get(), n, &p.x, &p.y); return p; }
336 double time(int n) const { return stroke_get_time(stroke.get(), n); }
337 + unsigned int size2() const { return stroke2 ? stroke_get_size(stroke2.get()) : 0; }
338 + bool trivial2() const { return size2() == 0 && button == 0; }
339 + Point points2(int n) const { Point p; stroke_get_point(stroke2.get(), n, &p.x, &p.y); return p; }
340 + double time2(int n) const { return stroke_get_time(stroke2.get(), n); }
341 bool is_timeout() const { return timeout; }
343 -BOOST_CLASS_VERSION(Stroke, 4)
344 +BOOST_CLASS_VERSION(Stroke, 5)
345 BOOST_CLASS_VERSION(Stroke::Point, 1)
347 class PreStroke : public std::vector<RTriple> {
348 diff -Naur easystroke-0.5.5.1/main.cc easystroke-0.5.5.1-3mod/main.cc
349 --- easystroke-0.5.5.1/main.cc 2011-08-16 10:11:40.000000000 +0200
350 +++ easystroke-0.5.5.1-3mod/main.cc 2011-12-06 23:01:09.000000000 +0100
353 static Window ping_window = 0;
354 static boost::shared_ptr<Trace> trace;
355 +static boost::shared_ptr<Trace> trace2;
356 static std::map<guint, guint> core_inv_map;
359 @@ -816,14 +817,26 @@
363 +#define MAX_PREV_LAST 20
364 +#define MAX_FINGERS 10
366 class StrokeHandler : public Handler, public sigc::trackable {
373 + RTriple last2, orig2;
375 int init_timeout, final_timeout, radius;
376 + int multi_finger_founds[ MAX_FINGERS ];
378 + RTriple prev_lasts[MAX_PREV_LAST];
380 + float min_dist_multi_finger;
381 + int multi_finger_tested_times;
386 @@ -838,25 +851,55 @@
388 RStroke finish(guint b) {
393 - if (!is_gesture || grabber->is_instant(button))
394 + RPreStroke c2 = cur2;
395 + if (verbosity >= 2)
396 + printf("finish: multi_finger=%d c.size=%d c2.size=%d\n",multi_finger,c->size(),c2->size());
399 + c2.reset(new PreStroke);
401 + if (multi_finger == 2) {
402 + if (!c2->valid()) {
403 + c2.reset(new PreStroke);
405 + if (verbosity >= 2)
406 + printf("two finger goes to one\n");
409 + if (!is_gesture || grabber->is_instant(button)) {
410 c.reset(new PreStroke);
411 - if (b && prefs.advanced_ignore.get())
412 + c2.reset(new PreStroke);
413 + if (verbosity >= 2)
414 + printf("reset stroke (1) is_gesture=%s is_instant=%s\n",
415 + is_gesture ? "true" : "false",
416 + grabber->is_instant(button) ? "true" : "false"
419 + if (b && prefs.advanced_ignore.get()) {
420 c.reset(new PreStroke);
421 - return Stroke::create(*c, button, b, false);
422 + c2.reset(new PreStroke);
423 + if (verbosity >= 2) printf("reset stroke (2)\n");
425 + return Stroke::create(*c, *c2, button, b, false, multi_finger);
430 printf("Aborting stroke...\n");
435 + RPreStroke c2 = cur2;
437 c.reset(new PreStroke);
438 + c2.reset(new PreStroke);
441 if (prefs.timeout_gestures.get() || grabber->is_click_hold(button))
442 - s = Stroke::create(*c, button, 0, true);
443 + s = Stroke::create(*c, *c2, button, 0, true, multi_finger);
444 parent->replace_child(AdvancedHandler::create(s, last, button, 0, cur));
451 - RStroke s = Stroke::create(ps, button, button, false);
453 + RStroke s = Stroke::create(ps, ps2, button, button, false, multi_finger);
454 parent->replace_child(AdvancedHandler::create(s, orig, button, button, cur));
457 @@ -881,13 +925,95 @@
460 virtual void motion(RTriple e) {
461 + if (verbosity >= 2) printf("-Valuating point (%g,%g)\n",e->x,e->y);
462 + if (multi_finger_tested_times < MAX_PREV_LAST + 20) {
463 + if (verbosity >= 4) printf("-Multi_finger\n");
464 + if (-1 || multi_finger_tested_times > MAX_PREV_LAST) {
465 + if (verbosity >= 3) printf("-Valuating multi_finger (%g,%g)\n",e->x,e->y);
466 + RTriple far_finger[ MAX_PREV_LAST ];
467 + int far_fingers = 0;
468 + for( int ndx = 0; ndx < num_prev_last; ndx++ ){
469 + if (verbosity >= 4) printf("-Valuating multi_finger %d(%g,%g)\n",ndx,prev_lasts[ndx]->x,prev_lasts[ndx]->y);
470 + bool far_from_all = true;
471 + for( int ndx_far = 0; ndx_far < far_fingers; ndx_far++ ){
472 + float far = hypot(far_finger[ndx_far]->x-prev_lasts[ndx]->x, far_finger[ndx_far]->y-prev_lasts[ndx]->y);
473 + if (verbosity >= 4){
474 + printf("-Valuating multi_finger %d far from prev %d(%g,%g) distance=%g\n",ndx,ndx_far,far_finger[ndx_far]->x,far_finger[ndx_far]->y,far);
476 + if ( far <= min_dist_multi_finger){
477 + if (verbosity >= 5) printf("-Valuating multi_finger %d far from prev is no so far to %d, distance: %g\n",ndx, ndx_far, far);
478 + far_from_all = false;
479 + far_finger[ndx_far] = prev_lasts[ndx];
483 + if (far_from_all) {
484 + if (verbosity >= 3) printf("-Valuating multi_finger %d far from prev added to list (%g,%g) at position %d\n",ndx,prev_lasts[ndx]->x,prev_lasts[ndx]->y,far_fingers);
485 + far_finger[far_fingers++] = prev_lasts[ndx];
488 + multi_finger_founds[ far_fingers ]++;
489 + if (verbosity >= 2) printf("-Valuating multi_finger found %d fingers, this time\n",far_fingers);
491 + for( int ndx = MAX_PREV_LAST - 1; ndx >= 1; ndx-- ){
492 + prev_lasts[ndx] = prev_lasts[ndx - 1];
495 + multi_finger_tested_times++;
496 + num_prev_last = multi_finger_tested_times;
497 + if (num_prev_last > MAX_PREV_LAST) {
498 + num_prev_last = MAX_PREV_LAST;
501 + if (multi_finger_tested_times != 1) {
506 + int ndx_multi_finger_founds;
507 + int max_founds = 0;
508 + for (ndx_multi_finger_founds = 0; ndx_multi_finger_founds < MAX_FINGERS; ndx_multi_finger_founds++) {
509 + if (verbosity >= 4){
510 + printf("-Valuating multi_finger_founds %d, for %d times\n",ndx_multi_finger_founds,multi_finger_founds[ndx_multi_finger_founds]);
512 + if (multi_finger_founds[ ndx_multi_finger_founds ] > max_founds) {
513 + multi_finger = ndx_multi_finger_founds;
514 + max_founds = multi_finger_founds[ ndx_multi_finger_founds ];
517 + if (verbosity >= 2){
518 + printf("-Valuating multi_finger found %d\n",multi_finger);
521 + float dist = hypot(e->x-last->x, e->y-last->y);
522 + // if (multi_finger > 1 && dist > min_dist_multi_finger) {
523 + if (dist > min_dist_multi_finger) {
524 + if (multi_finger == 2) {
529 + if (cur2->size() == 1) {
534 + if (verbosity >= 2) printf("-Valuating multi_finger added point to second finger\n");
535 + } else if (multi_finger > 2) {
536 + if (verbosity >= 3) printf("-Valuating multi_finger found %d fingers and this dist %g will be ignored\n",multi_finger,dist);
542 - float dist = hypot(e->x-orig->x, e->y-orig->y);
543 + dist = hypot(e->x-orig->x, e->y-orig->y);
544 if (!is_gesture && dist > 16) {
545 + if (verbosity >= 2) printf("Not gesture yet dist=%g\n",dist);
546 if (use_timeout && !final_timeout)
547 return abort_stroke();
548 init_connection.disconnect();
550 + if (verbosity >= 2) printf("Now is a gesture\n");
552 if (!drawing && dist > 4 && (!use_timeout || final_timeout)) {
555 RAction act = actions.get_action_list(grabber->current_class->get())->handle(s, ranking);
557 Ranking::queue_show(ranking, e);
558 + //if (!multi_finger || !act) {
561 return parent->replace_child(NULL);
562 @@ -978,6 +1105,12 @@
564 get_timeouts(prefs.timeout_profile.get(), &init_timeout, &final_timeout);
565 use_timeout = init_timeout;
568 + min_dist_multi_finger = 50.0;
569 + multi_finger_tested_times = 0;
571 + memset(multi_finger_founds,0,sizeof multi_finger_founds);
573 virtual void init() {
574 if (grabber->is_instant(button))
578 cur = PreStroke::create();
579 + cur2 = PreStroke::create();
581 + // cur2->add(orig);
584 if (final_timeout && final_timeout < 32 && radius < 16*32/final_timeout) {
586 init_connection = Glib::signal_timeout().connect(
587 sigc::mem_fun(*this, &StrokeHandler::timeout), init_timeout);
589 - ~StrokeHandler() { trace->end(); }
590 + ~StrokeHandler() { trace->end(); trace2->end(); }
591 virtual std::string name() { return "Stroke"; }
592 virtual Grabber::State grab_mode() { return Grabber::NONE; }
594 @@ -1114,7 +1249,7 @@
595 printf("Reloading gesture display\n");
596 queue(sigc::mem_fun(*this, &ReloadTrace::reload));
598 - void reload() { trace.reset(init_trace()); }
599 + void reload() { trace.reset(init_trace()); trace2.reset(init_trace()); }
602 static void schedule_reload_trace() { reload_trace.set_timeout(1000); }
603 @@ -1194,6 +1329,7 @@
604 XUngrabPointer(dpy, CurrentTime);
606 trace.reset(init_trace());
607 + trace2.reset(init_trace());
608 Glib::RefPtr<Gdk::Screen> screen = Gdk::Display::get_default()->get_default_screen();
609 g_signal_connect(screen->gobj(), "composited-changed", &schedule_reload_trace, NULL);
610 screen->signal_size_changed().connect(sigc::ptr_fun(&schedule_reload_trace));
611 @@ -1538,7 +1674,9 @@
621 diff -Naur easystroke-0.5.5.1/stroke.c easystroke-0.5.5.1-3mod/stroke.c
622 --- easystroke-0.5.5.1/stroke.c 2011-08-16 10:11:40.000000000 +0200
623 +++ easystroke-0.5.5.1-3mod/stroke.c 2011-12-06 23:05:55.000000000 +0100
634 stroke_t *stroke_alloc(int n) {
636 assert(s->capacity > s->n);
640 + s->minX = x; s->maxX = x; s->minY = y; s->maxY = y;
642 + if (x < s->minX) s->minX = x;
643 + if (x > s->maxX) s->maxX = x;
644 + if (y < s->minY) s->minY = y;
645 + if (y > s->maxY) s->maxY = y;
654 +double stroke_radians_difference(double alpha, double beta) {
655 + return angle_difference(alpha, beta);
658 +double stroke_calc_angle(struct point *p, struct point *q) {
659 + return atan2(p->y - q->y, p->x - q->x)/M_PI;
662 +/* subdivide the square with 5x5 grid */
663 +void point_position( const struct point *p, int *grid_x, int *grid_y) {
664 + *grid_x = p->x * 5.0;
665 + *grid_y = p->y * 5.0;
670 +double how_compatible_points(const struct point *p1, const struct point *p2) {
671 + int grid_1_x, grid_1_y, grid_2_x, grid_2_y;
672 + int diff_x, diff_y;
673 + double compatible = 0.0;
674 + point_position( p1, &grid_1_x, &grid_1_y );
675 + point_position( p2, &grid_2_x, &grid_2_y );
676 + diff_x = abs(grid_1_x - grid_2_x);
677 + diff_y = abs(grid_1_y - grid_2_y);
679 + case 0: compatible += 1.0; break;
680 + case 1: compatible += 0.5; break;
683 + case 0: compatible += 1.0; break;
684 + case 1: compatible += 0.5; break;
687 +printf("(%.3f[%d],%.3f[%d]) and (%.3f[%d],%.3f[%d]) = %.3f\n",
696 + return compatible / 2.0;
699 +double stroke_how_compatible(const stroke_t *stroke, const stroke_t *stroke2) {
700 + double compatible_start = how_compatible_points(&stroke->p[0],&stroke2->p[0]);
701 + double compatible_end = how_compatible_points(&stroke->p[stroke->n - 1],&stroke2->p[stroke2->n - 1]);
703 + return ( compatible_start + compatible_end ) / 2.0;
706 +double stroke_dist_start(const stroke_t *stroke, const stroke_t *stroke2) {
707 + return fabs(hypot(stroke->p[0].x - stroke2->p[0].x, stroke->p[0].y - stroke2->p[0].y));
710 +double stroke_dist_middle(const stroke_t *stroke, const stroke_t *stroke2) {
711 + return fabs(hypot(stroke->p[stroke->n / 2].x - stroke2->p[stroke2->n / 2].x, stroke->p[stroke->n / 2].y - stroke2->p[stroke2->n / 2].y));
714 +double stroke_dist_end(const stroke_t *stroke, const stroke_t *stroke2) {
715 + return fabs(hypot(stroke->p[stroke->n - 1].x - stroke2->p[stroke2->n - 1].x, stroke->p[stroke->n - 1].y - stroke2->p[stroke2->n - 1].y));
718 +double stroke_orient_start(const stroke_t *stroke, const stroke_t *stroke2) {
719 + return stroke_calc_angle(&stroke->p[0],&stroke2->p[0]);
722 +double stroke_orient_middle(const stroke_t *stroke, const stroke_t *stroke2) {
723 + return stroke_calc_angle(&stroke->p[stroke->n / 2],&stroke2->p[stroke2->n / 2]);
726 +double stroke_orient_end(const stroke_t *stroke, const stroke_t *stroke2) {
727 + return stroke_calc_angle(&stroke->p[stroke->n - 1],&stroke2->p[stroke2->n - 1]);
730 +void stroke_normalize(stroke_t *s,stroke_t *s2) {
732 + double minX = s->minX, minY = s->minY, maxX = s->maxX, maxY = s->maxY;
733 + if (s2->minX < s->minX) minX = s2->minX;
734 + if (s2->minY < s->minY) minY = s2->minY;
735 + if (s2->maxX > s->maxX) maxX = s2->maxX;
736 + if (s2->maxY > s->maxY) maxY = s2->maxY;
737 + s->minX = s2->minX = minX;
738 + s->minY = s2->minY = minY;
739 + s->maxX = s2->maxX = maxX;
740 + s->maxY = s2->maxY = maxY;
744 void stroke_finish(stroke_t *s) {
745 assert(s->capacity > 0);
748 for (int i = 0; i <= n; i++)
751 double minX = s->p[0].x, minY = s->p[0].y, maxX = minX, maxY = minY;
752 for (int i = 1; i <= n; i++) {
753 if (s->p[i].x < minX) minX = s->p[i].x;
755 if (s->p[i].y < minY) minY = s->p[i].y;
756 if (s->p[i].y > maxY) maxY = s->p[i].y;
758 - double scaleX = maxX - minX;
759 - double scaleY = maxY - minY;
761 + double scaleX = s->maxX - s->minX;
762 + double scaleY = s->maxY - s->minY;
763 double scale = (scaleX > scaleY) ? scaleX : scaleY;
764 if (scale < 0.001) scale = 1;
765 for (int i = 0; i <= n; i++) {
766 - s->p[i].x = (s->p[i].x-(minX+maxX)/2)/scale + 0.5;
767 - s->p[i].y = (s->p[i].y-(minY+maxY)/2)/scale + 0.5;
768 + s->p[i].x = (s->p[i].x-(s->minX+s->maxX)/2)/scale + 0.5;
769 + s->p[i].y = (s->p[i].y-(s->minY+s->maxY)/2)/scale + 0.5;
772 for (int i = 0; i < n; i++) {
773 s->p[i].dt = s->p[i+1].t - s->p[i].t;
774 - s->p[i].alpha = atan2(s->p[i+1].y - s->p[i].y, s->p[i+1].x - s->p[i].x)/M_PI;
775 + // s->p[i].alpha = atan2(s->p[i+1].y - s->p[i].y, s->p[i+1].x - s->p[i].x)/M_PI;
776 + s->p[i].alpha = stroke_calc_angle(&s->p[i+1], &s->p[i])/M_PI;
780 diff -Naur easystroke-0.5.5.1/stroke.h easystroke-0.5.5.1-3mod/stroke.h
781 --- easystroke-0.5.5.1/stroke.h 2011-08-16 10:11:40.000000000 +0200
782 +++ easystroke-0.5.5.1-3mod/stroke.h 2011-11-17 22:53:03.000000000 +0100
789 typedef struct _stroke_t stroke_t;
791 stroke_t *stroke_alloc(int n);
792 void stroke_add_point(stroke_t *stroke, double x, double y);
793 +void stroke_normalize(stroke_t *stroke, stroke_t *stroke2);
794 void stroke_finish(stroke_t *stroke);
795 void stroke_free(stroke_t *stroke);
797 int stroke_get_size(const stroke_t *stroke);
798 +double stroke_radians_difference(double alpha, double beta);
799 +double stroke_how_compatible(const stroke_t *stroke, const stroke_t *stroke2);
800 +double stroke_dist_start(const stroke_t *stroke, const stroke_t *stroke2);
801 +double stroke_dist_middle(const stroke_t *stroke, const stroke_t *stroke2);
802 +double stroke_dist_end(const stroke_t *stroke, const stroke_t *stroke2);
803 +double stroke_orient_start(const stroke_t *stroke, const stroke_t *stroke2);
804 +double stroke_orient_middle(const stroke_t *stroke, const stroke_t *stroke2);
805 +double stroke_orient_end(const stroke_t *stroke, const stroke_t *stroke2);
806 void stroke_get_point(const stroke_t *stroke, int n, double *x, double *y);
807 double stroke_get_time(const stroke_t *stroke, int n);
808 double stroke_get_angle(const stroke_t *stroke, int n);
809 diff -Naur easystroke-0.5.5.1/win.cc easystroke-0.5.5.1-3mod/win.cc
810 --- easystroke-0.5.5.1/win.cc 2011-08-30 13:04:10.000000000 +0200
811 +++ easystroke-0.5.5.1-3mod/win.cc 2011-11-14 08:40:21.000000000 +0100
813 const Cairo::RefPtr<Cairo::Context> ctx = Cairo::Context::create (surface);
814 x += width; y += width; w -= 2*width; h -= 2*width;
816 + int same_draws = multi_finger;
817 + if (same_draws < 1 || same_draws == 2) same_draws = 1;
820 ctx->set_line_width(2.0*width/(w+h));
822 z[n-1] = points(n-1) * (-sum);
823 for (int j = n-1; j > 0; j--)
824 z[j-1] = (z[j] - points(j)) * lambda;
825 + for (double f = 0.0; f < (double)same_draws; f++) {
826 for (int j = 0; j < n-1; j++) {
833 + p[0].x += f / 15.0; p[0].y += f / 15.0;
834 + p[3].x += f / 15.0; p[3].y += f / 15.0;
835 p[1] = p[0] + y[j] + z[j];
836 p[2] = p[3] - y[j+1] - z[j+1];
837 ctx->move_to(p[0].x, p[0].y);
838 ctx->curve_to(p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y);
839 + if (verbosity >= 4) printf(" draw1 (%g,%g)\n",p[0].x,p[0].y);
844 + if (multi_finger == 2 && n > 0) {
845 +//fprintf(NULL,"prova");
846 + if (verbosity >= 2) printf("draw second (size=%d)\n",n);
847 + std::vector<Point> y(n);
848 + y[0] = points2(0) * sum;
849 + for (int j = 0; j < n-1; j++)
850 + y[j+1] = (y[j] + points2(j)) * lambda;
851 + std::vector<Point> z(n);
852 + z[n-1] = points2(n-1) * (-sum);
853 + for (int j = n-1; j > 0; j--)
854 + z[j-1] = (z[j] - points2(j)) * lambda;
855 + for (int j = 0; j < n-1; j++) {
858 + ctx->set_source_rgba(time2(j), 0.0, 1.0-time2(j), 1.0);
860 + ctx->set_source_rgba(0.0, time2(j), 1.0-time2(j), 1.0);
863 + p[3] = points2(j+1);
864 + p[1] = p[0] + y[j] + z[j];
865 + p[2] = p[3] - y[j+1] - z[j+1];
866 + ctx->move_to(p[0].x, p[0].y);
867 + ctx->curve_to(p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y);
868 + if (verbosity >= 4) printf(" draw2 (%g,%g)\n",p[0].x,p[0].y);
872 } else if (!button) {
874 ctx->set_source_rgba(1.0, 1.0, 0.0, 1.0);