updated on Thu Jan 19 16:10:29 UTC 2012
[aur-mirror.git] / easystroke-mt / easystroke_multi_touch3.patch
blobeba90654f2b0d6ccb7b0fb1d156f80024f056e64
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
4 @@ -319,6 +319,7 @@
5 if (match < 0)
6 continue;
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
15 @@ -19,11 +19,12 @@
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) {
24 if (!is_composited())
25 throw std::runtime_error(_("'composite' not available"));
26 + composite = comp;
28 Glib::RefPtr<Gdk::Colormap> colormap = get_screen()->get_rgba_colormap();
29 if (colormap)
30 @@ -55,7 +56,7 @@
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));
39 @@ -91,11 +92,11 @@
42 void Popup::draw_line(Cairo::RefPtr<Cairo::Context> ctx) {
43 - if (!points.size())
44 + if (!composite->points.size())
45 return;
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
57 @@ -20,12 +20,15 @@
58 #include "main.h"
59 #include <list>
61 +class Composite;
63 class Popup : public Gtk::Window {
64 bool on_expose(GdkEventExpose* event);
65 void draw_line(Cairo::RefPtr<Cairo::Context> ctx);
66 Gdk::Rectangle rect;
67 + Composite *composite;
68 public:
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);
74 @@ -36,6 +39,7 @@
75 virtual void start_();
76 virtual void end_();
77 public:
78 + std::list<Trace::Point> points;
79 Composite();
80 virtual ~Composite();
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
85 @@ -0,0 +1,3 @@
86 +DFLAGS = -ggdb #-pg
87 +OFLAGS =
88 +#CXX = ccache g++
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
92 @@ -1,3 +0,0 @@
93 -DFLAGS = -ggdb #-pg
94 -OFLAGS =
95 -CXX = ccache g++
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
99 @@ -28,16 +28,30 @@
100 return e;
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;
108 if (ps.valid()) {
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;
115 + if (ps2.valid()) {
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);
121 + if (ps.valid()) {
122 stroke_finish(s);
123 stroke.reset(s, &stroke_free);
125 + if (ps2.valid()) {
126 + stroke_finish(s2);
127 + stroke2.reset(s2, &stroke_free);
131 int Stroke::compare(RStroke a, RStroke b, double &score) {
132 @@ -48,6 +62,8 @@
133 return -1;
134 if (a->button != b->button)
135 return -1;
136 + if (a->multi_finger != b->multi_finger)
137 + return -1;
138 if (a->trigger != b->trigger) {
139 if (a->trigger && b->trigger)
140 return -1;
141 @@ -62,10 +78,84 @@
142 else
143 return -1;
145 - double cost = stroke_compare(a->stroke.get(), b->stroke.get(), NULL, NULL);
146 + double cost;
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);
150 + } else {
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) {
163 + return -1;
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;
176 + } else {
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;
210 + } else {
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)
221 return -1;
222 score = MAX(1.0 - 2.5*cost, 0.0);
223 + if (verbosity >= 2) printf("score=%g\n", score);
224 if (a->timeout)
225 return score > 0.85;
226 else
227 @@ -96,11 +186,12 @@
229 RStroke Stroke::trefoil() {
230 PreStroke s;
231 + PreStroke s2;
232 const int n = 40;
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
244 @@ -36,6 +36,8 @@
246 int get_default_button();
248 +extern int verbosity;
250 struct Triple {
251 float x;
252 float y;
253 @@ -76,7 +78,7 @@
256 private:
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];
262 @@ -93,16 +95,24 @@
263 ar & button;
264 ar & trigger;
265 ar & timeout;
266 + ar & multi_finger;
267 + std::vector<Point> ps2;
268 + for (unsigned int i = 0; i < size2(); i++)
269 + ps2.push_back(points2(i));
270 + ar & ps2;
272 template<class Archive> void load(Archive & ar, const unsigned int version) {
273 std::vector<Point> ps;
274 ar & ps;
275 + stroke_t *s = NULL;
276 if (ps.size()) {
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);
281 - stroke_finish(s);
282 - stroke.reset(s, &stroke_free);
283 + if (version<5) {
284 + stroke_finish(s);
285 + stroke.reset(s, &stroke_free);
288 if (version == 0) return;
289 ar & button;
290 @@ -113,17 +123,39 @@
291 if (version < 3)
292 return;
293 ar & timeout;
294 + if (version < 5)
295 + return;
296 + ar & multi_finger;
297 + std::vector<Point> ps2;
298 + ar & ps2;
299 + stroke_t *s2 = NULL;
300 + if (ps2.size()) {
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);
306 + if (ps.size()) {
307 + stroke_finish(s);
308 + stroke.reset(s, &stroke_free);
310 + if (ps2.size()) {
311 + stroke_finish(s2);
312 + stroke2.reset(s2, &stroke_free);
316 public:
317 int trigger;
318 int button;
319 bool timeout;
320 + int multi_finger;
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;
333 @@ -139,9 +171,13 @@
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
351 @@ -65,6 +65,7 @@
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;
358 class Handler;
359 @@ -816,14 +817,26 @@
363 +#define MAX_PREV_LAST 20
364 +#define MAX_FINGERS 10
366 class StrokeHandler : public Handler, public sigc::trackable {
367 guint button;
368 RPreStroke cur;
369 + RPreStroke cur2;
370 bool is_gesture;
371 bool drawing;
372 RTriple last, orig;
373 + RTriple last2, orig2;
374 bool use_timeout;
375 int init_timeout, final_timeout, radius;
376 + int multi_finger_founds[ MAX_FINGERS ];
378 + RTriple prev_lasts[MAX_PREV_LAST];
379 + int multi_finger;
380 + float min_dist_multi_finger;
381 + int multi_finger_tested_times;
382 + int num_prev_last;
383 struct Connection {
384 sigc::connection c;
385 double dist;
386 @@ -838,25 +851,55 @@
388 RStroke finish(guint b) {
389 trace->end();
390 + trace2->end();
391 XFlush(dpy);
392 RPreStroke c = cur;
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());
397 + if (!c->valid()) {
398 + c = c2;
399 + c2.reset(new PreStroke);
401 + if (multi_finger == 2) {
402 + if (!c2->valid()) {
403 + c2.reset(new PreStroke);
404 + multi_finger = 1;
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"
417 + );
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);
428 bool timeout() {
429 if (verbosity >= 2)
430 printf("Aborting stroke...\n");
431 trace->end();
432 + trace2->end();
433 RPreStroke c = cur;
434 - if (!is_gesture)
435 + RPreStroke c2 = cur2;
436 + if (!is_gesture) {
437 c.reset(new PreStroke);
438 + c2.reset(new PreStroke);
440 RStroke s;
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));
445 XFlush(dpy);
446 return false;
447 @@ -864,7 +907,8 @@
449 void do_instant() {
450 PreStroke ps;
451 - RStroke s = Stroke::create(ps, button, button, false);
452 + PreStroke ps2;
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 @@
458 timeout();
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];
480 + break;
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];
494 + prev_lasts[0] = e;
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;
500 + /*
501 + if (multi_finger_tested_times != 1) {
502 + return;
504 + */
505 + } else {
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) {
525 + cur2->add(e);
526 + Trace::Point p;
527 + p.x = e->x;
528 + p.y = e->y;
529 + if (cur2->size() == 1) {
530 + trace2->start(p);
531 + } else {
532 + trace2->draw(p);
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);
538 + return;
541 cur->add(e);
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();
549 is_gesture = true;
550 + if (verbosity >= 2) printf("Now is a gesture\n");
552 if (!drawing && dist > 4 && (!use_timeout || final_timeout)) {
553 drawing = true;
554 @@ -939,6 +1065,7 @@
555 RAction act = actions.get_action_list(grabber->current_class->get())->handle(s, ranking);
556 if (!IS_CLICK(act))
557 Ranking::queue_show(ranking, e);
558 + //if (!multi_finger || !act) {
559 if (!act) {
560 XBell(dpy, 0);
561 return parent->replace_child(NULL);
562 @@ -978,6 +1105,12 @@
563 else
564 get_timeouts(prefs.timeout_profile.get(), &init_timeout, &final_timeout);
565 use_timeout = init_timeout;
566 + multi_finger = 1;
567 + multi_finger = 0;
568 + min_dist_multi_finger = 50.0;
569 + multi_finger_tested_times = 0;
570 + num_prev_last = 0;
571 + memset(multi_finger_founds,0,sizeof multi_finger_founds);
573 virtual void init() {
574 if (grabber->is_instant(button))
575 @@ -988,7 +1121,9 @@
576 final_timeout = 0;
578 cur = PreStroke::create();
579 + cur2 = PreStroke::create();
580 cur->add(orig);
581 + // cur2->add(orig);
582 if (!use_timeout)
583 return;
584 if (final_timeout && final_timeout < 32 && radius < 16*32/final_timeout) {
585 @@ -998,7 +1133,7 @@
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()); }
600 } reload_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 @@
613 Main::~Main() {
614 trace->end();
615 + trace2->end();
616 trace.reset();
617 + trace2.reset();
618 delete grabber;
619 delete kit;
620 XCloseDisplay(dpy);
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
624 @@ -37,6 +37,10 @@
625 int n;
626 int capacity;
627 struct point *p;
628 + double minX;
629 + double maxX;
630 + double minY;
631 + double maxY;
634 stroke_t *stroke_alloc(int n) {
635 @@ -52,6 +56,14 @@
636 assert(s->capacity > s->n);
637 s->p[s->n].x = x;
638 s->p[s->n].y = y;
639 + if (s->n==0) {
640 + s->minX = x; s->maxX = x; s->minY = y; s->maxY = y;
641 + } else {
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;
647 s->n++;
650 @@ -64,6 +76,95 @@
651 d -= 2.0;
652 return d;
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;
668 +#include <stdio.h>
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);
678 + switch(diff_x){
679 + case 0: compatible += 1.0; break;
680 + case 1: compatible += 0.5; break;
682 + switch(diff_y){
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",
688 + p1->x,grid_1_x,
689 + p1->y,grid_1_y,
690 + p2->x,grid_2_x,
691 + p2->y,grid_2_y,
692 + compatible / 2.0
693 + );
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) {
731 + if (s && 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);
746 @@ -78,6 +179,7 @@
748 for (int i = 0; i <= n; i++)
749 s->p[i].t /= total;
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;
754 @@ -85,18 +187,20 @@
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
783 @@ -21,15 +21,25 @@
784 #endif
786 struct _stroke_t;
787 +struct point;
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
812 @@ -25,6 +25,8 @@
813 const Cairo::RefPtr<Cairo::Context> ctx = Cairo::Context::create (surface);
814 x += width; y += width; w -= 2*width; h -= 2*width;
815 ctx->save();
816 + int same_draws = multi_finger;
817 + if (same_draws < 1 || same_draws == 2) same_draws = 1;
818 ctx->translate(x,y);
819 ctx->scale(w,h);
820 ctx->set_line_width(2.0*width/(w+h));
821 @@ -41,6 +43,7 @@
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++) {
827 // j -> j+1
828 if (inv)
829 @@ -50,12 +53,45 @@
830 Point p[4];
831 p[0] = points(j);
832 p[3] = points(j+1);
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);
840 ctx->stroke();
843 + n = size2();
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++) {
856 + // j -> j+1
857 + if (inv)
858 + ctx->set_source_rgba(time2(j), 0.0, 1.0-time2(j), 1.0);
859 + else
860 + ctx->set_source_rgba(0.0, time2(j), 1.0-time2(j), 1.0);
861 + Point p[4];
862 + p[0] = points2(j);
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);
869 + ctx->stroke();
872 } else if (!button) {
873 if (inv)
874 ctx->set_source_rgba(1.0, 1.0, 0.0, 1.0);