html/mouse.pl


   1 # See http://wouter.coekaerts.be/site/irssi/mouse
   2 # based on irssi mouse patch by mirage: http://darksun.com.pt/mirage/irssi/
   3 
   4 # Copyright (C) 2005-2009  Wouter Coekaerts <wouter@coekaerts.be>
   5 #
   6 # This program is free software; you can redistribute it and/or modify
   7 # it under the terms of the GNU General Public License as published by
   8 # the Free Software Foundation; either version 2 of the License, or
   9 # (at your option) any later version.
  10 #
  11 # This program is distributed in the hope that it will be useful,
  12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 # GNU General Public License for more details.
  15 #
  16 # You should have received a copy of the GNU General Public License
  17 # along with this program; if not, write to the Free Software
  18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  19 
  20 use strict;
  21 use Irssi qw(signal_emit settings_get_str active_win signal_stop settings_add_str settings_add_bool settings_get_bool signal_add signal_add_first);
  22 use Math::Trig;
  23 
  24 use vars qw($VERSION %IRSSI);
  25 
  26 $VERSION = '1.0.0';
  27 %IRSSI = (
  28 	authors  	=> 'Wouter Coekaerts',
  29 	contact  	=> 'wouter@coekaerts.be',
  30 	name    	=> 'mouse',
  31 	description 	=> 'control irssi using mouse clicks and gestures',
  32 	license 	=> 'GPLv2 or later',
  33 	url     	=> 'http://wouter.coekaerts.be/irssi/',
  34 	changed  	=> '2009-05-16',
  35 );
  36 
  37 my @BUTTONS = ('', '_middle', '_right');
  38 
  39 my $mouse_xterm_status = -1; # -1:off 0,1,2:filling mouse_xterm_combo
  40 my @mouse_xterm_combo = (3, 0, 0); # 0:button 1:x 2:y
  41 my @mouse_xterm_previous; # previous contents of mouse_xterm_combo
  42 
  43 sub mouse_enable {
  44 	print STDERR "\e[?1000h"; # start tracking 
  45 }
  46 
  47 sub mouse_disable {
  48 	print STDERR "\e[?1000l"; # stop tracking 
  49 }
  50 
  51 # Handle mouse event (button press or release)
  52 sub mouse_event {
  53 	my ($b, $x, $y, $oldb, $oldx, $oldy) = @_;
  54 	my ($xd, $yd);
  55 	my ($distance, $angle);
  56 
  57 	# uhm, in the patch the scrollwheel didn't work for me, but this does:
  58 	if ($b == 64) {
  59 		cmd("mouse_scroll_up");
  60 	} elsif ($b == 65) {
  61 		cmd("mouse_scroll_down")
  62 	}
  63 
  64 	# proceed only if a button is being released
  65 	return if ($b != 3);
  66 
  67 	return unless (0 <= $oldb && $oldb <= 2);
  68 	my $button = $BUTTONS[$oldb];
  69 
  70 	# if it was a mouse click of the left button (press and release in the same position)
  71 	if ($x == $oldx && $y == $oldy) {
  72 		cmd("mouse" . $button . "_click");
  73 		return;
  74 	}
  75 
  76 	# otherwise, find mouse gestures
  77 	$xd = $x - $oldx;
  78 	$yd = -1 * ($y - $oldy);
  79 	$distance = sqrt($xd*$xd + $yd*$yd);
  80 	# ignore small gestures
  81 	if ($distance < 3) {
  82 		return;
  83 	}
  84 	$angle = asin($yd/$distance) * 180 / 3.14159265358979;
  85 	if ($angle < 20 && $angle > -20 && $xd > 0) {
  86 		if ($distance <= 40) {
  87 			cmd("mouse" . $button . "_gesture_right");
  88 		} else {
  89 			cmd("mouse" . $button . "_gesture_bigright");
  90 		}
  91 	} elsif ($angle < 20 && $angle > -20 && $xd < 0) {
  92 		if ($distance <= 40) {
  93 			cmd("mouse" . $button . "_gesture_left");
  94 		} else {
  95 			cmd("mouse" . $button . "_gesture_bigleft");
  96 		}
  97 	} elsif ($angle > 40) {
  98 		cmd("mouse" . $button . "_gesture_up");
  99 	} elsif ($angle < -40) {
 100 		cmd("mouse" . $button . "_gesture_down");
 101 	}
 102 }
 103 
 104 # executes the command configured in the given setting
 105 sub cmd
 106 {
 107 	my ($setting) = @_;
 108 	signal_emit("send command", settings_get_str($setting), active_win->{'active_server'}, active_win->{'active'});
 109 }
 110 
 111 
 112 signal_add_first("gui key pressed", sub {
 113 	my ($key) = @_;
 114 	if ($mouse_xterm_status != -1) {
 115 		if ($mouse_xterm_status == 0 && ($mouse_xterm_previous[0] != $mouse_xterm_combo[0])) { # if combo is starting, and previous what not a move (button not changed)
 116 			@mouse_xterm_previous = @mouse_xterm_combo;
 117 		}
 118 		$mouse_xterm_combo[$mouse_xterm_status] = $key-32;
 119 		$mouse_xterm_status++;
 120 		if ($mouse_xterm_status == 3) {
 121 			$mouse_xterm_status = -1;
 122 			# match screen coordinates
 123 			$mouse_xterm_combo[1]--;
 124 			$mouse_xterm_combo[2]--;
 125 			mouse_event($mouse_xterm_combo[0], $mouse_xterm_combo[1], $mouse_xterm_combo[2], $mouse_xterm_previous[0], $mouse_xterm_previous[1], $mouse_xterm_previous[2]);
 126 		}
 127 		signal_stop();
 128 	}
 129 });
 130 
 131 sub UNLOAD {
 132 	mouse_disable();
 133 }
 134 
 135 if ($ENV{"TERM"} !~ /^rxvt|screen|xterm(-color)?$/) {
 136 	die "Your terminal doesn't seem to support this.";
 137 }
 138 
 139 mouse_enable();
 140 
 141 Irssi::command("/^bind meta-[M /mouse_xterm"); # FIXME evil
 142 Irssi::command_bind("mouse_xterm", sub {$mouse_xterm_status = 0;});
 143 Irssi::command_bind 'mouse' => sub {
 144 	my ($data, $server, $item) = @_;
 145 	$data =~ s/\s+$//g;
 146 	Irssi::command_runsub('mouse', $data, $server, $item);
 147 };
 148 
 149 # temporarily disable mouse handling. Useful for copy-pasting without touching the keyboard (pressing shift)
 150 Irssi::command_bind 'mouse tempdisable' => sub {
 151 	my ($data, $server, $item) = @_;
 152 	my $seconds = ($data eq '') ? 5 : $data; # optional argument saying how many seconds, defaulting to 5
 153 	mouse_disable();
 154 	Irssi::timeout_add_once($seconds * 1000, 'mouse_enable', undef); # turn back on after $second seconds
 155 };
 156 
 157 for my $button (@BUTTONS) {
 158 	settings_add_str("lookandfeel", "mouse" . $button . "_click", "/mouse tempdisable 5");
 159 	settings_add_str("lookandfeel", "mouse" . $button . "_gesture_up", "/window last");
 160 	settings_add_str("lookandfeel", "mouse" . $button . "_gesture_down", "/window goto active");
 161 	settings_add_str("lookandfeel", "mouse" . $button . "_gesture_left", "/window prev");
 162 	settings_add_str("lookandfeel", "mouse" . $button . "_gesture_bigleft", "/eval window prev;window prev");
 163 	settings_add_str("lookandfeel", "mouse" . $button . "_gesture_right", "/window next");
 164 	settings_add_str("lookandfeel", "mouse" . $button . "_gesture_bigright", "/eval window next;window next");
 165 }
 166 
 167 settings_add_str("lookandfeel", "mouse_scroll_up", "/scrollback goto -10");
 168 settings_add_str("lookandfeel", "mouse_scroll_down", "/scrollback goto +10");