Here's a prototype/proof-of-concept for an ordinary screen.
I've written it in Perl/Tk and tested on Cygwin and Windows XP. It's basically a Text widget with lots of content. Moving the mouse around at (what I consider to be) normal speed does nothing; swiping the mouse horizontally, vertically or diagonally will scroll the window in the same direction.
You may need to tweak a few numbers:
-
The geometry ($mw->geometry('1200x900+50+50'); is widthxheight+x-offset+y-offset - see the geometry() method in Tk::Wm for details (or just comment that line out and position/resize manually).
-
The distance the mouse has to travel before the gesture is recognised is governed by X_MIN_DISTANCE_VARIATION and Y_MIN_DISTANCE_VARIATION - the settings I have worked for me but your mileage may vary.
-
The amount of scrolling is controlled by X_UNIT_SCROLL and Y_UNIT_SCROLL - again, you may want to customise these.
-
Recognition of whether the mouse is being moved at normal speed or being swiped is determined by MAX_TIME_VARIATION - mouse acceleration, pointer speed and similar settings you currently have in place will affect this.
Here's the code:
#!perl
use strict;
use warnings;
use Time::HiRes qw{gettimeofday tv_interval};
use Tk;
use constant {
MAX_TIME_VARIATION => 0.01,
X_MIN_DISTANCE_VARIATION => 25,
Y_MIN_DISTANCE_VARIATION => 18,
X_UNIT_SCROLL => 4,
Y_UNIT_SCROLL => 3,
};
my $mw = MainWindow->new(-title => 'Mouse Gesture Test');
$mw->geometry('1200x900+50+50');
my $w_text = $mw->Scrolled('Text',
-scrollbars => 'osoe',
-wrap => 'none',
)->pack(-fill => 'both', -expand => 1);
my ($xpos, $ypos);
my $t0 = [gettimeofday];
$w_text->bind('<Motion>', [\&mouse_gesture, Ev('x'), Ev('y')]);
populate_text_widget($w_text);
$mw->Button(-text => q{Exit}, -command => sub { exit })->pack();
MainLoop;
sub mouse_gesture {
my ($w, $x, $y) = @_;
# Once-off initialisation
if (! defined $xpos) {
$xpos = $x;
$ypos = $y;
return;
}
my $t1 = [gettimeofday];
if (tv_interval($t0, $t1) > MAX_TIME_VARIATION) {
$t0 = $t1;
$xpos = $x;
$ypos = $y;
}
else {
if (abs(abs($xpos) - abs($x)) > X_MIN_DISTANCE_VARIATION) {
$t0 = $t1;
for (1 .. X_UNIT_SCROLL) {
$w->xviewScroll($xpos < $x ? 1 : -1, q{units});
}
$xpos = $x;
}
if (abs(abs($ypos) - abs($y)) > Y_MIN_DISTANCE_VARIATION) {
$t0 = $t1;
for (1 .. Y_UNIT_SCROLL) {
$w->yviewScroll($ypos < $y ? 1 : -1, q{units});
}
$ypos = $y;
}
}
return;
}
sub populate_text_widget {
my $w = shift;
my $long_string = '';
for ('a' .. 'z') {
$long_string .= $_ x 20;
}
for (1 .. 500) {
$w->insert('end',
"This is line $_. It's really long ... $long_string\n"
);
}
}
Enjoy!
|