├── README.md ├── eventKey.cfg ├── nScroll └── eventKey.cfg └── xSwipe.pl /README.md: -------------------------------------------------------------------------------- 1 | xSwipe 2 | ====================== 3 | xSwipe is multitouch gesture recognizer. 4 | This script make your linux PC able to recognize swipes. 5 | 6 | **Ubuntu15.04, or later** 7 | I released [Fusuma](https://github.com/iberianpig/fusuma), it use libinput driver and suppport pinch zoom . 8 | You should try [Fusuma](https://github.com/iberianpig/fusuma) instead of xSwipe if you use Ubuntu15.04, or later. 9 | It need not depend on older version synaptics driver, and it works well with libinput driver supported by 15.04 or later as standard. 10 | 11 | ## Usage 12 | 13 | Before running the script, you must first do some preparations. 14 | 15 | 1. Download xSwipe 16 | 2. Install X11::GUITest 17 | 3. Enable SHMConfig 18 | 19 | ### 1. Download xSwipe 20 | Type below code, download xSwipe from github 21 | 22 | $ cd ~ 23 | $ wget https://github.com/iberianpig/xSwipe/archive/master.zip 24 | $ unzip master.zip 25 | 26 | ### 2. Install X11::GUITest 27 | 28 | To install libx11-guitest-perl from synaptic package manager 29 | Or run the script on the terminal run as 30 | 31 | $ sudo apt-get install libx11-guitest-perl 32 | 33 | --- 34 | #### NOTE: If using Ubuntu14.04, or later 35 | ##### Install older version synaptics driver that is compatible with xSwipe. 36 | 37 | ```bash 38 | $ sudo apt-get install -y git build-essential libevdev-dev autoconf automake libmtdev-dev xorg-dev xutils-dev libtool 39 | $ sudo apt-get remove -y xserver-xorg-input-synaptics 40 | $ git clone https://github.com/Chosko/xserver-xorg-input-synaptics.git 41 | $ cd xserver-xorg-input-synaptics 42 | $ ./autogen.sh 43 | $ ./configure --exec_prefix=/usr 44 | $ make 45 | $ sudo make install 46 | ``` 47 | --- 48 | 49 | ### 3. Enable SHMConfig 50 | 51 | Open /etc/X11/xorg.conf.d/50-synaptics.conf with your favorite text editor and edit it to enable SHMConfig 52 | 53 | $ sudo gedit /etc/X11/xorg.conf.d/50-synaptics.conf 54 | 55 | **NOTE**:You will need to create the /etc/X11/xorg.conf.d/ directory and create 50-synaptics.conf if it doesn't exist yet. 56 | `$ sudo mkdir /etc/X11/xorg.conf.d/` 57 | 58 | ##### /etc/X11/xorg.conf.d/50-synaptics.conf 59 | 60 | Section "InputClass" 61 | Identifier "evdev touchpad catchall" 62 | Driver "synaptics" 63 | MatchDevicePath "/dev/input/event*" 64 | MatchIsTouchpad "on" 65 | Option "Protocol" "event" 66 | Option "SHMConfig" "on" 67 | EndSection 68 | 69 | To reflect SHMConfig, restart your session. 70 | 71 | That's it for preparation. 72 | 73 | ## Run xSwipe 74 | 75 | To run xSwipe, type below code on terminal. 76 | 77 | $ perl ~/xSwipe-master/xSwipe.pl 78 | 79 | **Note:You should run xSwipe.pl in same directory as "eventKey.cfg" .** 80 | 81 | You can use "swipe" with 3 or 4 fingers, they can call an event. 82 | Additionally, some gestures are available. 83 | 84 | * *edge-swipe* : swipe with 2 fingers from outside edge(need to enable with option). 85 | * *long-press* : hold pressure for 0.5 seconds with 3 or 4 fingers. 86 | 87 | ### Option 88 | 89 | * `-d RATE` : 90 | *RATE* is sensitivity to swipe.Default value is 1. 91 | Shorten swipe-length by half (e.g.,`$ perl xSwipe.pl -d 0.5`) 92 | * `-m INTERVAL` : 93 | *INTERVAL* is how often synclient monitor changes to the touchpad state. 94 | Default value is 10(ms). 95 | Set 50ms as monitoring-span. (e.g.,`$ perl xSwipe.pl -m 50`) 96 | * `-n` : 97 | Natural scroll like Macbook, use "/nScroll/eventKey.cfg". 98 | * `-e` : 99 | Enable edge-swipe 100 | 101 | ## Customize 102 | You can customize the settings for gestues to edit eventKey.cfg. 103 | Please check this article, ["How to customize gesture"](https://github.com/iberianpig/xSwipe/wiki/Customize-eventKey.cfg). 104 | 105 | ### Bindable gestures 106 | * 3/4/5 fingers swipe 107 | * 2/3/4/5 fingers long-press 108 | * 2/3/4 fingers edge-swipe 109 | - *2fingers edge-swipe*: only swipe-left/right from right/left edge 110 | - *3fingers edge-swipe*: only swipe-down from top egde 111 | 112 | ### Example shortcut keys 113 | * go back/forward on browser (Alt+Left, Alt+Right) 114 | * open/close a tab on browser (Ctrl+t/Ctrl+w) 115 | * move tabs (Ctrl+Tab, Ctrl+Shift+Tab) 116 | * move workspaces (Alt+Ctrl+Lert, Alt+Ctrl+Right, Alt+Ctrl+Up, Alt+Ctrl+Down) 117 | * move a window (Alt+F7) 118 | * open launcher (Alt+F8) 119 | * open a terminal (Ctrl+Alt+t) 120 | * close a window (Alt+F4) 121 | 122 | Please let me know if you have any questions about this program. 123 | -------------------------------------------------------------------------------- /eventKey.cfg: -------------------------------------------------------------------------------- 1 | #Please config this file if you like. 2 | 3 | { 4 | 'gnome'=>{ 5 | swipe2 =>{ 6 | press => "default", 7 | }, 8 | swipe3=>{ 9 | right => "LAL/RIG", # alt + right 10 | left => "LAL/LEF", # alt + left 11 | down => "LCT/LAL/DOWN", # ctrl + alt + down 12 | up => "LCT/LAL/UP", # ctrl + alt + up 13 | press => "LAL/F7", # alt + F7 14 | }, 15 | swipe4=>{ 16 | right => "LCT/t", # ctrl + t 17 | left => "LCT/w", # ctrl + w 18 | down => "LCT/Fn/LSK/d", # ctrl + Fn + super + d 19 | up => "LSK", # super 20 | press => "LAL/F8", # alt + F8 21 | }, 22 | swipe5=>{ 23 | right => "LAL/RIG", # alt + right 24 | left => "LAL/LEF", # alt + left 25 | down => "LCT/LAL/DOWN", # ctrl + alt + down 26 | up => "LCT/LAL/UP", # ctrl + alt + up 27 | press => "LAL/F7", # alt + F7 28 | }, 29 | edge_swipe2=>{ 30 | right => "LCT/TAB", # ctrl + tab 31 | left => "LSH/LCT/TAB", # shift + ctrl + tab 32 | }, 33 | edge_swipe3=>{ 34 | down => "LAL/F4", # alt + F4 35 | up => "LCT/LAL/t", # ctrl + alt + t 36 | }, 37 | edge_swipe4=>{ 38 | down => "LAL/F4", # alt + F4 39 | up => "LCT/LAL/t", # ctrl + alt + t 40 | } 41 | }, 42 | 'ubuntu'=>{ 43 | swipe2 =>{ 44 | press => "LAL/F8", 45 | }, 46 | swipe3 =>{ 47 | right => "LCT/LAL/RIG", # ctrl + alt + right 48 | left => "LCT/LAL/LEF", # ctrl + alt + left 49 | down => "LCT/LAL/DOWN", # ctrl + alt + down 50 | up => "LCT/LAL/UP", # ctrl + alt + up 51 | press => "LAL/F7", # alt + F7 52 | }, 53 | swipe4=>{ 54 | right => "RAL/LAL/RIG", # alt + right 55 | left => "RAL/LAL/LEF", # alt + left 56 | down => "LSK/w", # super + w 57 | up => "LSK/s", # super + s 58 | press => "LAL/F8", # alt + F8 59 | }, 60 | swipe5=>{ 61 | right => "LAL/RIG", # alt + right 62 | left => "LAL/LEF", # alt + left 63 | down => "LCT/LAL/DOWN", # ctrl + alt + down 64 | up => "LCT/LAL/UP", # ctrl + alt + up 65 | press => "LAL/F7", # alt + F7 66 | }, 67 | edge_swipe2=>{ 68 | right => "LCT/TAB", # ctrl + tab 69 | left => "LSH/LCT/TAB", # shift + ctrl + tab 70 | }, 71 | edge_swipe3=>{ 72 | down => "LAL/F4", # alt + F4 73 | up => "LCT/LAL/t", # ctrl + alt + t 74 | }, 75 | edge_swipe4=>{ 76 | down => "LAL/F4", # alt + F4 77 | up => "LCT/LAL/t", # ctrl + alt + t 78 | } 79 | }, 80 | 'gnome-classic'=>{ 81 | swipe2 =>{ 82 | press => "LAL/F8", 83 | }, 84 | swipe3 =>{ 85 | right => "LCT/LAL/RIG", # ctrl + alt + right 86 | left => "LCT/LAL/LEF", # ctrl + alt + left 87 | down => "LCT/LAL/DOWN", # ctrl + alt + down 88 | up => "LCT/LAL/UP", # ctrl + alt + up 89 | press => "LAL/F7", # alt + F7 90 | }, 91 | swipe4=>{ 92 | right => "RAL/LAL/RIG", # alt + right 93 | left => "RAL/LAL/LEF", # alt + left 94 | down => "LSK/w", # super + w 95 | up => "LSK/s", # super + s 96 | press => "LAL/F8", # alt + F8 97 | }, 98 | swipe5=>{ 99 | right => "LAL/RIG", # alt + right 100 | left => "LAL/LEF", # alt + left 101 | down => "LCT/LAL/DOWN", # ctrl + alt + down 102 | up => "LCT/LAL/UP", # ctrl + alt + up 103 | press => "LAL/F7", # alt + F7 104 | }, 105 | edge_swipe2=>{ 106 | right => "LCT/TAB", # ctrl + tab 107 | left => "LSH/LCT/TAB", # shift + ctrl + tab 108 | }, 109 | edge_swipe3=>{ 110 | down => "LAL/F4", # alt + F4 111 | up => "LCT/LAL/t", # ctrl + alt + t 112 | }, 113 | edge_swipe4=>{ 114 | down => "LAL/F4", # alt + F4 115 | up => "LCT/LAL/t", # ctrl + alt + t 116 | } 117 | }, 118 | 'pantheon'=>{ 119 | swipe2 =>{ 120 | press => "default", 121 | }, 122 | swipe3 =>{ 123 | right => "LAL/RIG", # alt + right 124 | left => "LAL/LEF", # alt + left 125 | down => "LCT/w", # ctrl + w 126 | up => "LCT/t", # ctrl + t 127 | press => "LAL/F7", # alt + F7 128 | }, 129 | swipe4=>{ 130 | right => "LSK/RIG", # super + right 131 | left => "LSK/LEF", # super + left 132 | down => "LSK/w", # super + w 133 | up => "LSK/s", # super + s 134 | press => "LAL/F8", # alt + F8 135 | }, 136 | swipe5=>{ 137 | right => "LAL/RIG", # alt + right 138 | left => "LAL/LEF", # alt + left 139 | down => "LCT/LAL/DOWN", # ctrl + alt + down 140 | up => "LCT/LAL/UP", # ctrl + alt + up 141 | press => "LAL/F7", # alt + F7 142 | }, 143 | edge_swipe2=>{ 144 | right => "LCT/TAB", # ctrl + tab 145 | left => "LSH/LCT/TAB", # shift + ctrl + tab 146 | }, 147 | edge_swipe3=>{ 148 | down => "LAL/F4", # alt + F4 149 | up => "LCT/LAL/t", # ctrl + alt + t 150 | }, 151 | edge_swipe4=>{ 152 | down => "LAL/F4", # alt + F4 153 | up => "LCT/LAL/t", # ctrl + alt + t 154 | } 155 | }, 156 | 'other'=>{ 157 | swipe2 =>{ 158 | press => "default", 159 | }, 160 | swipe3 =>{ 161 | right => "LAL/RIG", # alt + right 162 | left => "LAL/LEF", # alt + left 163 | down => "LCT/w", # ctrl + w 164 | up => "LCT/t", # ctrl + t 165 | press => "LAL/F7", # alt + F7 166 | }, 167 | swipe4=>{ 168 | right => "LCT/LAL/RIG", # ctrl + alt + right 169 | left => "LCT/LAL/LEF", # ctrl + alt + left 170 | down => "LCT/LAL/DOWN", # ctrl + alt + down 171 | up => "LCT/LAL/UP", # ctrl + alt + up 172 | press => "LAL/F8", # alt + F8 173 | }, 174 | swipe5=>{ 175 | right => "LAL/RIG", # alt + right 176 | left => "LAL/LEF", # alt + left 177 | down => "LCT/LAL/DOWN", # ctrl + alt + down 178 | up => "LCT/LAL/UP", # ctrl + alt + up 179 | press => "LAL/F7", # alt + F7 180 | }, 181 | edge_swipe2=>{ 182 | right => "LCT/TAB", # ctrl + tab 183 | left => "LSH/LCT/TAB", # shift + ctrl + tab 184 | }, 185 | edge_swipe3=>{ 186 | down => "LAL/F4", # alt + F4 187 | up => "LCT/LAL/t", # ctrl + alt + t 188 | }, 189 | edge_swipe4=>{ 190 | down => "LAL/F4", # alt + F4 191 | up => "LCT/LAL/t", # ctrl + alt + t 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /nScroll/eventKey.cfg: -------------------------------------------------------------------------------- 1 | #Please config this file if you like. 2 | #Natural Scroll 3 | { 4 | 'gnome'=>{ 5 | swipe2 =>{ 6 | press => "default", 7 | }, 8 | swipe3=>{ 9 | right => "LAL/LEF", # alt + left 10 | left => "LAL/RIG", # alt + right 11 | down => "LCT/LAL/UP", # ctrl + alt + up 12 | up => "LCT/LAL/DOWN", # ctrl + alt + down 13 | press => "LAL/F7", # alt + F7 14 | }, 15 | swipe4=>{ 16 | right => "LCT/t", # ctrl + t 17 | left => "LCT/w", # ctrl + w 18 | down => "LCT/Fn/LSK/d", # ctrl + Fn + super + d 19 | up => "LSK", # super 20 | press => "LAL/F8", # alt + F8 21 | }, 22 | swipe5=>{ 23 | right => "LAL/LEF", # alt + left 24 | left => "LAL/RIG", # alt + right 25 | down => "LCT/LAL/UP", # ctrl + alt + up 26 | up => "LCT/LAL/DOWN", # ctrl + alt + down 27 | press => "LAL/F7", # alt + F7 28 | }, 29 | edge_swipe2=>{ 30 | right => "LCT/TAB", # ctrl + tab 31 | left => "LSH/LCT/TAB", # shift + ctrl + tab 32 | }, 33 | edge_swipe3=>{ 34 | down => "LAL/F4", # alt + F4 35 | up => "LCT/LAL/t", # ctrl + alt + t 36 | }, 37 | edge_swipe4=>{ 38 | down => "LAL/F4", # alt + F4 39 | up => "LCT/LAL/t", # ctrl + alt + t 40 | } 41 | }, 42 | 'ubuntu'=>{ 43 | swipe2 =>{ 44 | press => "default", 45 | }, 46 | swipe3 =>{ 47 | right => "LCT/LAL/LEF", # ctrl + alt + left 48 | left => "LCT/LAL/RIG", # ctrl + alt + right 49 | down => "LCT/LAL/UP", # ctrl + alt + up 50 | up => "LCT/LAL/DOWN", # ctrl + alt + down 51 | press => "LAL/F7", # alt + F7 52 | }, 53 | swipe4=>{ 54 | right => "RAL/LAL/LEF", # alt + left 55 | left => "RAL/LAL/RIG", # alt + right 56 | down => "LSK/w", # super + w 57 | up => "LSK/s", # super + s 58 | press => "LAL/F8", # alt + F8 59 | }, 60 | swipe5=>{ 61 | right => "LAL/LEF", # alt + left 62 | left => "LAL/RIG", # alt + right 63 | down => "LCT/LAL/UP", # ctrl + alt + up 64 | up => "LCT/LAL/DOWN", # ctrl + alt + down 65 | press => "LAL/F7", # alt + F7 66 | }, 67 | edge_swipe2=>{ 68 | right => "LCT/TAB", # ctrl + tab 69 | left => "LSH/LCT/TAB", # shift + ctrl + tab 70 | }, 71 | edge_swipe3=>{ 72 | down => "LAL/F4", # alt + F4 73 | up => "LCT/LAL/t", # ctrl + alt + t 74 | }, 75 | edge_swipe4=>{ 76 | down => "LAL/F4", # alt + F4 77 | up => "LCT/LAL/t", # ctrl + alt + t 78 | } 79 | }, 80 | 'gnome-classic'=>{ 81 | swipe2 =>{ 82 | press => "default", 83 | }, 84 | swipe3 =>{ 85 | right => "LCT/LAL/LEF", # ctrl + alt + left 86 | left => "LCT/LAL/RIG", # ctrl + alt + right 87 | down => "LCT/LAL/UP", # ctrl + alt + up 88 | up => "LCT/LAL/DOWN", # ctrl + alt + down 89 | press => "LAL/F7", # alt + F7 90 | }, 91 | swipe4=>{ 92 | right => "RAL/LAL/LEF", # alt + left 93 | left => "RAL/LAL/RIG", # alt + right 94 | down => "LSK/w", # super + w 95 | up => "LSK/s", # super + s 96 | press => "LAL/F8", # alt + F8 97 | }, 98 | swipe5=>{ 99 | right => "LAL/LEF", # alt + left 100 | left => "LAL/RIG", # alt + right 101 | down => "LCT/LAL/UP", # ctrl + alt + up 102 | up => "LCT/LAL/DOWN", # ctrl + alt + down 103 | press => "LAL/F7", # alt + F7 104 | }, 105 | edge_swipe2=>{ 106 | right => "LCT/TAB", # ctrl + tab 107 | left => "LSH/LCT/TAB", # shift + ctrl + tab 108 | }, 109 | edge_swipe3=>{ 110 | down => "LAL/F4", # alt + F4 111 | up => "LCT/LAL/t", # ctrl + alt + t 112 | }, 113 | edge_swipe4=>{ 114 | down => "LAL/F4", # alt + F4 115 | up => "LCT/LAL/t", # ctrl + alt + t 116 | } 117 | }, 118 | 'pantheon'=>{ 119 | swipe2 =>{ 120 | press => "default", 121 | }, 122 | swipe3 =>{ 123 | right => "LAL/LEF", # alt + left 124 | left => "LAL/RIG", # alt + right 125 | down => "LCT/w", # ctrl + w 126 | up => "LCT/t", # ctrl + t 127 | press => "LAL/F7", # alt + F7 128 | }, 129 | swipe4=>{ 130 | right => "LSK/LEF", # super + left 131 | left => "LSK/RIG", # super + right 132 | down => "LSK/w", # super + w 133 | up => "LSK/s", # super + s 134 | press => "LAL/F8", # alt + F8 135 | }, 136 | swipe5=>{ 137 | right => "LAL/LEF", # alt + left 138 | left => "LAL/RIG", # alt + right 139 | down => "LCT/LAL/UP", # ctrl + alt + up 140 | up => "LCT/LAL/DOWN", # ctrl + alt + down 141 | press => "LAL/F7", # alt + F7 142 | }, 143 | edge_swipe2=>{ 144 | right => "LCT/TAB", # ctrl + tab 145 | left => "LSH/LCT/TAB", # shift + ctrl + tab 146 | }, 147 | edge_swipe3=>{ 148 | down => "LAL/F4", # alt + F4 149 | up => "LCT/LAL/t", # ctrl + alt + t 150 | }, 151 | edge_swipe4=>{ 152 | down => "LAL/F4", # alt + F4 153 | up => "LCT/LAL/t", # ctrl + alt + t 154 | } 155 | }, 156 | 'other'=>{ 157 | swipe2 =>{ 158 | press => "default", 159 | }, 160 | swipe3 =>{ 161 | right => "LAL/LEF", # alt + left 162 | left => "LAL/RIG", # alt + right 163 | down => "LCT/w", # ctrl + w 164 | up => "LCT/t", # ctrl + t 165 | press => "LAL/F7", # alt + F7 166 | }, 167 | swipe4=>{ 168 | right => "LCT/LAL/LEF", # ctrl + alt + left 169 | left => "LCT/LAL/RIG", # ctrl + alt + right 170 | down => "LCT/LAL/DOWN", # ctrl + alt + down 171 | up => "LCT/LAL/UP", # ctrl + alt + up 172 | press => "LAL/F8", # alt + F8 173 | }, 174 | swipe5=>{ 175 | right => "LAL/LEF", # alt + left 176 | left => "LAL/RIG", # alt + right 177 | down => "LCT/LAL/UP", # ctrl + alt + up 178 | up => "LCT/LAL/DOWN", # ctrl + alt + down 179 | press => "LAL/F7", # alt + F7 180 | }, 181 | edge_swipe2=>{ 182 | right => "LCT/TAB", # ctrl + tab 183 | left => "LSH/LCT/TAB", # shift + ctrl + tab 184 | }, 185 | edge_swipe3=>{ 186 | down => "LAL/F4", # alt + F4 187 | up => "LCT/LAL/t", # ctrl + alt + t 188 | }, 189 | edge_swipe4=>{ 190 | down => "LAL/F4", # alt + F4 191 | up => "LCT/LAL/t", # ctrl + alt + t 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /xSwipe.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | ################################################ 3 | # # #### # # # ##### ###### 4 | # # # # # # # # # 5 | ## #### # # # # # ##### 6 | ## # # ## # # ##### # 7 | # # # # ## ## # # # 8 | # # #### # # # # ###### 9 | ################################################ 10 | use strict; 11 | use Time::HiRes(); 12 | use X11::GUITest qw( :ALL ); 13 | use FindBin; 14 | #debug 15 | # use Smart::Comments; 16 | 17 | my $natural_scroll = 0; 18 | my $base_dist = 0.1; 19 | my $polling_interval = 10; 20 | my $conf_file_name = "eventKey.cfg"; 21 | my $n_scroll_conf_file_name = "nScroll/eventKey.cfg"; 22 | my $edge_swipe = 0; 23 | 24 | while(my $ARGV = shift){ 25 | ### $ARGV 26 | if ($ARGV eq '-n'){ 27 | $natural_scroll = 1; 28 | }elsif ($ARGV eq '-d'){ 29 | if ($ARGV[0] > 0){ 30 | $base_dist = $base_dist * $ARGV[0]; 31 | ### $base_dist 32 | shift; 33 | }else{ 34 | print "Set a value greater than 0\n"; 35 | exit(1); 36 | } 37 | }elsif ($ARGV eq '-m'){ 38 | if ($ARGV[0] > 0){ 39 | $polling_interval = $ARGV[0]; 40 | ### $polling_interval 41 | shift; 42 | }else{ 43 | print "Set a value greater than 0\n"; 44 | exit(1); 45 | } 46 | }elsif ($ARGV eq '-e'){ 47 | $edge_swipe = 1; 48 | }else{ 49 | print " 50 | Available Options 51 | -d RATE 52 | RATE sensitivity to swipe 53 | RATE > 0, default value is 1 54 | -m INTERVAL 55 | INTERVAL how often synclient monitor changes to the touchpad state 56 | INTERVAL > 0, default value is 10 (ms) 57 | -n 58 | Natural Scrolling, like a macbook 59 | setting file path=nScroll/eventKey.cfg 60 | -e 61 | Enable edge-swipe 62 | \n"; 63 | exit(1); 64 | } 65 | } 66 | 67 | open (scroll_setting, "synclient -l | grep ScrollDelta | grep -v -e Circ | ")or die "can't synclient -l"; 68 | my @scroll_setting = ; 69 | close(file_handle); 70 | 71 | my $vert_scroll_delta = abs((split "= ", $scroll_setting[0])[1]); 72 | my $horiz_scroll_delta = abs((split "= ", $scroll_setting[1])[1]); 73 | 74 | &init_synclient($natural_scroll); 75 | 76 | open (area_setting, "synclient -l | grep Edge | grep -v -e Area -e Motion -e Scroll | ")or die "can't synclient -l"; 77 | my @area_setting = ; 78 | close(file_handle); 79 | 80 | my $left_edge = (split "= ", $area_setting[0])[1]; 81 | my $right_edge = (split "= ", $area_setting[1])[1]; 82 | my $top_edge = (split "= ", $area_setting[2])[1]; 83 | my $bottom_edge = (split "= ", $area_setting[3])[1]; 84 | 85 | my $touchpad_size_h = abs($top_edge - $bottom_edge); 86 | my $touchpad_size_w = abs($left_edge - $right_edge); 87 | my $x_min_thredshould = $touchpad_size_w * $base_dist; 88 | my $y_min_thredshould = $touchpad_size_h * $base_dist; 89 | my $inner_edge_left = $left_edge + $x_min_thredshould/3; 90 | my $inner_edge_right = $right_edge - $x_min_thredshould/3; 91 | my $inner_edge_top = $top_edge + $y_min_thredshould; 92 | my $inner_edge_bottom = $bottom_edge - $y_min_thredshould; 93 | 94 | ### @area_setting 95 | ### $touchpad_size_h 96 | ### $touchpad_size_w 97 | ### $x_min_thredshould 98 | ### $y_min_thredshould 99 | ### $inner_edge_left 100 | ### $inner_edge_right 101 | ### $inner_edge_top 102 | ### $inner_edge_bottom 103 | 104 | #load config 105 | my $script_dir = $FindBin::Bin;#CurrentPath 106 | my $conf = require $script_dir."/".$conf_file_name; 107 | open (file_handle, "pgrep -lf ^gnome-session |")or die "can't pgrep -lf ^gnome-session"; 108 | my @data = ; 109 | my $session_name = (split "session=", $data[0])[1]; 110 | close(file_handle); 111 | chomp($session_name); 112 | # If $session_name is empty (gnome-session doesn't work), try to find it with $DESKTOP_SESSION 113 | if (not length $session_name){ 114 | open (desktop_session, 'echo $DESKTOP_SESSION |')or die 'can\'t echo $DESKTOP_SESSION'; 115 | $session_name = ; 116 | close(desktop_session); 117 | chomp($session_name); 118 | } 119 | $session_name = ("$session_name" ~~ $conf) ? "$session_name" : 'other'; 120 | ### $session_name 121 | 122 | my @swipe3_right = split "/", ($conf->{$session_name}->{swipe3}->{right}); 123 | my @swipe3_left = split "/", ($conf->{$session_name}->{swipe3}->{left}); 124 | my @swipe3_down = split "/", ($conf->{$session_name}->{swipe3}->{down}); 125 | my @swipe3_up = split "/", ($conf->{$session_name}->{swipe3}->{up}); 126 | 127 | my @swipe4_right = split "/", ($conf->{$session_name}->{swipe4}->{right}); 128 | my @swipe4_left = split "/", ($conf->{$session_name}->{swipe4}->{left}); 129 | my @swipe4_down = split "/", ($conf->{$session_name}->{swipe4}->{down}); 130 | my @swipe4_up = split "/", ($conf->{$session_name}->{swipe4}->{up}); 131 | 132 | my @swipe5_right = split "/", ($conf->{$session_name}->{swipe5}->{right}); 133 | my @swipe5_left = split "/", ($conf->{$session_name}->{swipe5}->{left}); 134 | my @swipe5_down = split "/", ($conf->{$session_name}->{swipe5}->{down}); 135 | my @swipe5_up = split "/", ($conf->{$session_name}->{swipe5}->{up}); 136 | 137 | my @edge_swipe2_right = split "/", ($conf->{$session_name}->{edge_swipe2}->{right}); 138 | my @edge_swipe2_left = split "/", ($conf->{$session_name}->{edge_swipe2}->{left}); 139 | my @edge_swipe3_down = split "/", ($conf->{$session_name}->{edge_swipe3}->{down}); 140 | my @edge_swipe3_up = split "/", ($conf->{$session_name}->{edge_swipe3}->{up}); 141 | my @edge_swipe4_down = split "/", ($conf->{$session_name}->{edge_swipe4}->{down}); 142 | my @edge_swipe4_up = split "/", ($conf->{$session_name}->{edge_swipe4}->{up}); 143 | my @long_press2 = split "/", ($conf->{$session_name}->{swipe2}->{press}); 144 | my @long_press3 = split "/", ($conf->{$session_name}->{swipe3}->{press}); 145 | my @long_press4 = split "/", ($conf->{$session_name}->{swipe4}->{press}); 146 | my @long_press5 = split "/", ($conf->{$session_name}->{swipe5}->{press}); 147 | 148 | my @x_hist1 = (); # x coordinate history (1 finger) 149 | my @y_hist1 = (); # y coordinate history (1 finger) 150 | my @x_hist2 = (); # x coordinate history (2 fingers) 151 | my @y_hist2 = (); # y coordinate history (2 fingers) 152 | my @x_hist3 = (); # x coordinate history (3 fingers) 153 | my @y_hist3 = (); # y coordinate history (3 fingers) 154 | my @x_hist4 = (); # x coordinate history (4 fingers) 155 | my @y_hist4 = (); # y coordinate history (4 fingers) 156 | my @x_hist5 = (); # x coordinate history (5 fingers) 157 | my @y_hist5 = (); # y coordinate history (5 fingers) 158 | 159 | my $axis = 0; 160 | my $rate = 0; 161 | 162 | my $touch_state = "not_swiping"; # touchState={0/1/2} 0=notSwiping, 1=Swiping, 2=edge_swiping 163 | my $last_time = 0; # time monitor for TouchPad event reset 164 | my $event_time = 0; # ensure enough time has passed between events 165 | my @event_string = ("default"); # the event to execute 166 | 167 | my $curr_wind = GetInputFocus(); 168 | die "couldn't get input window" unless $curr_wind; 169 | open(INFILE,"synclient -m $polling_interval |") or die "can't read from synclient"; 170 | while(my $line = ){ 171 | chomp($line); 172 | my($time, $x, $y, $z, $f, $w) = split " ", $line; 173 | next if($time =~ /time/); #ignore header lines 174 | if($time - $last_time > 5){ 175 | &init_synclient($natural_scroll); 176 | }#if time reset 177 | $last_time = $time; 178 | $axis = 0; 179 | $rate = 0; 180 | if($f == 1){ 181 | if($touch_state eq "not_swiping"){ 182 | if(in_edge_area($x, "")){ 183 | $touch_state = "edge_swiping"; 184 | }else{ 185 | $touch_state = "swiping"; 186 | } 187 | } 188 | clean_hist(2 ,3 ,4 ,5); 189 | if ($touch_state eq "edge_swiping"){ 190 | push @x_hist1, $x; 191 | push @y_hist1, $y; 192 | $axis = get_axis(\@x_hist1, \@y_hist1, 2, 0.1); 193 | if($axis eq "x"){ 194 | $rate = get_rate(@x_hist1); 195 | $touch_state = "edge_swiping"; 196 | }elsif($axis eq "y"){ 197 | $rate = get_rate(@y_hist1); 198 | $touch_state = "edge_swiping"; 199 | } 200 | } 201 | 202 | }elsif($f == 2){ 203 | if($touch_state eq "not_swiping"){ 204 | if(in_edge_area($x, "")){ 205 | $touch_state = "edge_swiping"; 206 | &switch_touch_pad("Off"); 207 | }else{ 208 | $touch_state = "swiping"; 209 | } 210 | } 211 | clean_hist(1, 3, 4, 5); 212 | push @x_hist2, $x; 213 | push @y_hist2, $y; 214 | $axis = get_axis(\@x_hist2, \@y_hist2, 2, 0.1); 215 | if($axis eq "x"){ 216 | $rate = get_rate(@x_hist2); 217 | }elsif($axis eq "y"){ 218 | $rate = get_rate(@y_hist2); 219 | }elsif($axis eq "z"){ 220 | $axis = get_axis(\@x_hist2, \@y_hist2, 30, 0.5); 221 | if($axis eq "z"){ 222 | } 223 | } 224 | 225 | }elsif($f == 3){ 226 | if($touch_state eq "not_swiping" ){ 227 | if(in_edge_area("", $y)){ 228 | $touch_state = "edge_swiping"; 229 | }else{ 230 | $touch_state = "swiping"; 231 | } 232 | } 233 | clean_hist(1, 2, 4, 5); 234 | push @x_hist3, $x; 235 | push @y_hist3, $y; 236 | $axis = get_axis(\@x_hist3, \@y_hist3, 5, 0.5); 237 | if($axis eq "x"){ 238 | $rate = get_rate(@x_hist3); 239 | }elsif($axis eq "y"){ 240 | $rate = get_rate(@y_hist3); 241 | }elsif($axis eq "z"){ 242 | $axis = get_axis(\@x_hist3, \@y_hist3, 30, 0.5); 243 | if($axis eq "z"){ 244 | } 245 | } 246 | 247 | }elsif($f == 4){ 248 | if($touch_state eq "not_swiping" ){ 249 | if(in_edge_area("", $y)){ 250 | $touch_state = "edge_swiping"; 251 | }else{ 252 | $touch_state = "swiping"; 253 | } 254 | } 255 | clean_hist(1, 2, 3, 5); 256 | push @x_hist4, $x; 257 | push @y_hist4, $y; 258 | $axis = get_axis(\@x_hist4, \@y_hist4, 5, 0.5); 259 | if($axis eq "x"){ 260 | $rate = get_rate(@x_hist4); 261 | }elsif($axis eq "y"){ 262 | $rate = get_rate(@y_hist4); 263 | }elsif($axis eq "z"){ 264 | $axis = get_axis(\@x_hist4, \@y_hist4, 30, 0.5); 265 | if($axis eq "z"){ 266 | } 267 | } 268 | 269 | }elsif($f == 5){ 270 | if($touch_state eq "not_swiping" ){ 271 | if(in_edge_area("", $y)){ 272 | $touch_state = "edge_swiping"; 273 | }else{ 274 | $touch_state = "not_swiping"; 275 | } 276 | } 277 | clean_hist(1, 2, 3 ,4); 278 | push @x_hist5, $x; 279 | push @y_hist5, $y; 280 | $axis = get_axis(\@x_hist5, \@y_hist5, 5, 0.5); 281 | if($axis eq "x"){ 282 | $rate = get_rate(@x_hist5); 283 | }elsif($axis eq "y"){ 284 | $rate = get_rate(@y_hist5); 285 | } 286 | }else{ 287 | clean_hist(1, 2, 3, 4, 5); 288 | if($touch_state ne "not_swiping"){ 289 | $touch_state = "not_swiping"; 290 | &switch_touch_pad("On"); 291 | } 292 | } 293 | 294 | 295 | #detect action 296 | if ($axis ne 0){ 297 | @event_string = set_event_string($f,$axis,$rate,$touch_state); 298 | clean_hist(1, 2, 3, 4, 5); 299 | } 300 | 301 | # only process one event per time window 302 | if( $event_string[0] ne "default" ){ 303 | ### ne default 304 | if( abs($time - $event_time) > 0.2 ){ 305 | ### $time - $event_time got: $time - $event_time 306 | $event_time = $time; 307 | PressKey $_ foreach(@event_string); 308 | ReleaseKey $_ foreach(reverse @event_string); 309 | ### @event_string 310 | }# if enough time has passed 311 | @event_string = ("default"); 312 | }#if non default event 313 | }#synclient line in 314 | close(INFILE); 315 | 316 | ###init 317 | sub init_synclient{ 318 | ### init_synclient 319 | # &switch_touch_pad("On"); 320 | my $natural_scroll = $_[0]; 321 | if($natural_scroll == 1){ 322 | $conf_file_name = $n_scroll_conf_file_name; 323 | `synclient VertScrollDelta=-$vert_scroll_delta HorizScrollDelta=-$horiz_scroll_delta ClickFinger3=1 TapButton3=2`; 324 | }else{ 325 | `synclient VertScrollDelta=$vert_scroll_delta HorizScrollDelta=$horiz_scroll_delta ClickFinger3=1 TapButton3=2`; 326 | } 327 | } 328 | 329 | sub switch_touch_pad{ 330 | open(TOUCHPADOFF,"synclient -l | grep TouchpadOff |") or die "can't read from synclient"; 331 | my $touch_pad_off = ; 332 | close(TOUCHPADOFF); 333 | chomp($touch_pad_off); 334 | my $touch_pad_off = (split "= ", $touch_pad_off)[1]; 335 | ### $touch_pad_off 336 | my $switch_flag = shift; 337 | if($switch_flag eq 'Off'){ 338 | if($touch_pad_off eq '0'){ 339 | `synclient TouchPadOff=1`; 340 | } 341 | }elsif($switch_flag eq "On"){ 342 | if($touch_pad_off ne '0' ){ 343 | `synclient TouchPadOff=0`; 344 | } 345 | } 346 | } 347 | 348 | sub get_axis{ 349 | my($x_hist, $y_hist, $max, $threshould_rate)=@_; 350 | if(@$x_hist > $max or @$y_hist > $max){ 351 | my $x0 = @$x_hist[0]; 352 | my $y0 = @$y_hist[0]; 353 | my $xmax = @$x_hist[$max]; 354 | my $ymax = @$y_hist[$max]; 355 | my $x_dist = abs( $x0 - $xmax ); 356 | my $y_dist = abs( $y0 - $ymax ); 357 | if($x_dist > $y_dist){ 358 | if($x_dist > $x_min_thredshould * $threshould_rate){ 359 | return "x"; 360 | }else{ 361 | return "z"; 362 | } 363 | }else{ 364 | if($y_dist > $y_min_thredshould * $threshould_rate){ 365 | return "y"; 366 | }else{ 367 | return "z"; 368 | } 369 | } 370 | } 371 | return 0; 372 | } 373 | 374 | sub get_rate{ 375 | my @hist = @_; 376 | my @srt = sort {$a <=> $b} @hist; 377 | my @rev_srt = sort {$b <=> $a} @hist; 378 | if( "@srt" eq "@hist" ){ 379 | return "+"; 380 | }elsif( "@rev_srt" eq "@hist" ){ 381 | return "-"; 382 | }#if forward or backward 383 | return 0; 384 | } 385 | 386 | sub clean_hist{ 387 | while(my $arg = shift){ 388 | if($arg == 1){ 389 | @x_hist1 = (); 390 | @y_hist1 = (); 391 | }elsif($arg == 2){ 392 | @x_hist2 = (); 393 | @y_hist2 = (); 394 | }elsif($arg == 3){ 395 | @x_hist3 = (); 396 | @y_hist3 = (); 397 | }elsif($arg == 4){ 398 | @x_hist4 = (); 399 | @y_hist4 = (); 400 | }elsif($arg == 5){ 401 | @x_hist5 = (); 402 | @y_hist5 = (); 403 | } 404 | } 405 | } 406 | 407 | sub in_edge_area{ 408 | unless ($edge_swipe){ 409 | return 0; 410 | } 411 | my($x, $y)=@_; 412 | if($x and ( ($x < $inner_edge_left)or($inner_edge_right < $x) )){ 413 | return 1; 414 | } 415 | if($y and ( ($y < $inner_edge_top)or($inner_edge_bottom < $y) )){ 416 | return 1; 417 | } 418 | return 0; 419 | } 420 | 421 | #return @event_string $_[0] 422 | sub set_event_string{ 423 | my($f, $axis, $rate, $touch_state)=@_; 424 | if($f == 2){ 425 | if($axis eq "x"){ 426 | if($rate eq "+"){ 427 | if($touch_state eq "edge_swiping"){ 428 | return @edge_swipe2_right; 429 | } 430 | }elsif($rate eq "-"){ 431 | if($touch_state eq "edge_swiping"){ 432 | return @edge_swipe2_left; 433 | } 434 | } 435 | }elsif($axis eq "z"){ 436 | if($rate eq "0"){ 437 | if($touch_state eq "swiping"){ 438 | return @long_press2; 439 | } 440 | } 441 | } 442 | }elsif($f == 3){ 443 | if($axis eq "x"){ 444 | if($rate eq "+"){ 445 | return @swipe3_right; 446 | }elsif($rate eq "-"){ 447 | return @swipe3_left; 448 | } 449 | }elsif($axis eq "y"){ 450 | if($rate eq "+"){ 451 | if($touch_state eq "edge_swiping"){ 452 | return @edge_swipe3_down; 453 | } 454 | return @swipe3_down; 455 | }elsif($rate eq "-"){ 456 | if($touch_state eq "edge_swiping"){ 457 | return @edge_swipe3_up; 458 | } 459 | return @swipe3_up; 460 | } 461 | }elsif($axis eq "z"){ 462 | if($rate eq "0"){ 463 | return @long_press3; 464 | } 465 | } 466 | }elsif($f == 4){ 467 | if($axis eq "x"){ 468 | if($rate eq "+"){ 469 | return @swipe4_right; 470 | }elsif($rate eq "-"){ 471 | return @swipe4_left; 472 | } 473 | }elsif($axis eq "y"){ 474 | if($rate eq "+"){ 475 | if($touch_state eq "edge_swiping"){ 476 | return @edge_swipe4_down; 477 | } 478 | return @swipe4_down; 479 | }elsif($rate eq "-"){ 480 | if($touch_state eq "edge_swiping"){ 481 | return @edge_swipe4_up; 482 | } 483 | return @swipe4_up; 484 | } 485 | }elsif($axis eq "z"){ 486 | if($rate eq "0"){ 487 | return @long_press4; 488 | } 489 | } 490 | }elsif($f == 5){ 491 | if($axis eq "x"){ 492 | if($rate eq "+"){ 493 | return @swipe5_right; 494 | }elsif($rate eq "-"){ 495 | return @swipe5_left; 496 | } 497 | }elsif($axis eq "y"){ 498 | if($rate eq "+"){ 499 | return @swipe5_down; 500 | }elsif($rate eq "-"){ 501 | return @swipe5_up; 502 | } 503 | }elsif($axis eq "z"){ 504 | if($rate eq "0"){ 505 | return @long_press5; 506 | } 507 | } 508 | } 509 | return "default"; 510 | } 511 | 512 | --------------------------------------------------------------------------------