gadgetoid
Posts: 152
Joined: Wed Mar 07, 2012 9:58 pm

Re: [how to] enable long touch as right click

Sat Feb 27, 2016 3:24 pm

I chanced upon this thread again recently, and decided to have another dig for a solution. This may be a better or worse one, but it seems to work well for me: https://github.com/Plippo/twofing

You either need some grasp of evdev rules ( which I don't have, yet ) or knowledge of which event device your touchscreen is. But I just compiled twofing and ran it like so ( actually I tweaked the binary but that's no use to you ):

Code: Select all

./twofing --debug /dev/input/event2
If that works for you, you can drop the debug flag.

If it works. Be amazed. It supports two finger right click ( none of that pesky long press nonsense ) and some other gestures, too.

It will change the panning behavior in Epiphany from one finger to two.

A useful stop-gap solution ;)

lilgman
Posts: 9
Joined: Wed Nov 04, 2015 2:26 pm
Location: Lesotho, Africa

Re: [how to] enable long touch as right click

Sun Feb 28, 2016 3:33 am

Could you explain in a little more detail for a noob how you got this working please. Especially how you compiled.

Thanks!

gadgetoid
Posts: 152
Joined: Wed Mar 07, 2012 9:58 pm

Re: [how to] enable long touch as right click

Sun Feb 28, 2016 11:23 am

Sorry, I totally forgot to link the developers original site, here: http://plippo.de/p/twofing

Build instructions are posted, and are relatively straight forward.

You don't need to perform the step: "Install the daemon by calling sudo make install"

This will install a bunch of evdev rules which are completely useless on your Pi. No harm, but no use either!

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: [how to] enable long touch as right click

Sun Feb 28, 2016 12:38 pm

I seem to be missing something.

1) Downloaded and extracted the source.
2) Installed the needed packages

Code: Select all

sudo apt-get install build-essential libx11-dev libxtst-dev libxi-dev x11proto-randr-dev libxrandr-dev
3) Ran "make"

Code: Select all

>$ make
gcc -c -Wall -O2 twofingemu.c
gcc -c -Wall -O2 gestures.c
gcc -c -Wall -O2 easing.c
gcc -o twofing twofingemu.o gestures.o easing.o -lm -lpthread -lXtst -lXrandr -lX11 -lXi
Tried to run it

Code: Select all

>$ ./twofing --debug /dev/input/event2
twofing, the two-fingered daemon
Version 0.1.2.20120708

/dev/twofingtouch: No such file or directory
EDIT: I went ahead and used "make install", then rebooted, but still get the same error. I tried creating a "twofingtouch" sym link "/dev/twofingtouch" to /dev/input/event2 and that didn't work either, I always get the same error "/dev/twofingtouch: No such file or directory". So I removed the sym link.

After running "make install" I now have a "twofing" file in /usr/bin/, owned by root with 755 permissions.
/etc/udev/rules.d now contains the file "70-touchscreen-egalax.rules" owned by root with 644 permissions.
But there is still no /dev/twofingtouch so the program won't start.

gadgetoid
Posts: 152
Joined: Wed Mar 07, 2012 9:58 pm

Re: [how to] enable long touch as right click

Sun Feb 28, 2016 3:45 pm

Might be the source from the package, versus the one from GitHub, doesn't support the ability to specify an alternate device on the command line.

I suspect you can fix it by opening up main.c, finding "/dev/twofingtouch" and replacing it with "/dev/input/event2"

Achievement unlocked: You're now a polyglot!

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: [how to] enable long touch as right click

Sun Feb 28, 2016 5:09 pm

I did a "make uninstall" to clear things up. Changed "/dev/twofingtouch" to "/dev/input/event2" in "twofingemu.c".
Then I did another "sudo make install" and rebooted. It requires sudo since the install copies "twofing" to /usr/bin.

That took care of the alternate device problem and the error changed to

Code: Select all

>$ twofing --debug
twofing, the two-fingered daemon
Version 0.1.2.20120708

/dev/input/event2: No such file or directory
The version is the same as shown on github, so the source should be OK.
So I headed on over to /dev/input/ and found I don't have an "event2", hell I don't even have an "event1" :D .

Code: Select all

>$ ls -l
total 0
crw-rw---- 1 root input 13, 64 Feb 28 11:10 event0
crw-rw---- 1 root input 13, 63 Feb 28 11:10 mice
crw-rw---- 1 root input 13, 32 Feb 28 11:10 mouse0
The touchscreen works fine, but obviously I don't have an event 2 input. I don't know much about inputs and events. Would another event be added if I plug in a mouse? I use the touchscreen, or run Synergy if it's on my desk so that I use my PC mouse and keyboard. Or maybe in my case I should use event0?

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: [how to] enable long touch as right click

Sun Feb 28, 2016 11:17 pm

I changed the input to event0 and that works. Using the sym link probably would have worked too, instead of changing the ".c" file, if I had linked /dev/twofing to event0 instead of event2.

On the first run it tried to calibrate and failed for some reason, so it used defaults, but it seems to be good.

That is nice having a right click function again, I really missed that after upgrading to Jessie. I have trouble closing windows with that little "x", you have to hit it just right, and that's never on the first try, so I end up pecking at it. Now I can just touch the title bar with two fingers and then touch "Close" on the dropdown menu. First time, every time... Thanks!

lilgman
Posts: 9
Joined: Wed Nov 04, 2015 2:26 pm
Location: Lesotho, Africa

Re: [how to] enable long touch as right click

Wed Mar 02, 2016 2:18 am

Thanks for your help. I can confirm that making a symlink from /dev/input/event0 to /dev/twofingtouch works. LOVE having right-click again! :D

Edit for noobs like me: the command to start this magic if you symlink like I did is

Code: Select all

 ./twofing  /dev/input/event0

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: [how to] enable long touch as right click

Wed Mar 02, 2016 3:03 am

If you do a

Code: Select all

sudo cp ~/twofing /usr/bin/twofing
and did a

Code: Select all

sudo ln -s /dev/input/event0 /dev/twofingtouch
Then you should be able to start it from anywhere by just using "twofing". Or you could put it in the desktop autostart file so it would start with the desktop.

fruit-uk
Posts: 609
Joined: Wed Aug 06, 2014 4:19 pm
Location: Suffolk, UK

Re: [how to] enable long touch as right click

Wed Mar 02, 2016 7:17 am

This can be done without altering the sources at all, and not running make install either.
simply call

Code: Select all

./twofing-0.1.2/twofing /dev/input/event0
as user (twofing-0.1.2 dir name is from memory so may be wrong)

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: [how to] enable long touch as right click

Wed Mar 02, 2016 12:04 pm

True, that's already been established. I was just pointing out that copying the twofing script to /usr/bin and linking the input you can start it with just;
"twofing" rather than having to use "./twofing-0.1.2/twofing /dev/input/event0"

Makro
Posts: 3
Joined: Wed Mar 02, 2016 9:28 pm

Re: [how to] enable long touch as right click

Wed Mar 02, 2016 9:41 pm

Hi all,

Thanks for resolving right-click problem.
But, sorry for my NOOBS question, is it possible to give a really simple "how to" to enable this twofingers function in Jessie with the official 7" display? In a terminal? step by step?

I'm quit new with RP and Debian and I can't follow all your explanations.

I belive it would be useful for other beginners like me, and we'll be very thanksfull to you!!

Best regards

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: [how to] enable long touch as right click

Thu Mar 03, 2016 12:03 pm

Sure, I'm setting up another SDCard today which will be for my RPi3 (when it finally arrives), and I'll be starting from scratch on that one. I can post a simple step by step (composed as I go along) that won't have all the confusion about the input changes halfway through.

Makro
Posts: 3
Joined: Wed Mar 02, 2016 9:28 pm

Re: [how to] enable long touch as right click

Wed Mar 09, 2016 8:05 am

Wonderful! Thank you. We are waiting impatiently :)

Ben72a
Posts: 1
Joined: Sat May 07, 2016 12:35 pm

Re: [how to] enable long touch as right click

Sat May 07, 2016 12:39 pm

@ JimmyN

Are you still working on the step-by-step manual for noobs like me?

That would be great! :D

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: [how to] enable long touch as right click

Sat May 07, 2016 4:03 pm

Ben72a wrote:@ JimmyN

Are you still working on the step-by-step manual for noobs like me?

That would be great! :D
Here you go
viewtopic.php?f=108&t=138575

ArnisA
Posts: 1
Joined: Wed May 25, 2016 6:34 pm

Re: [how to] enable long touch as right click

Wed May 25, 2016 6:46 pm

There is nothing wrong with Jessie. I got right click working on my ADS7846 Touchscreen only with increased setting of
Option "EmulateThirdButtonMoveThreshold" "50" (your mileage may vary).
I should note that it does not work when I press screen with finger but I get right click emulated when pressing with fingernail or sharper object.

a human
Posts: 4
Joined: Sat Oct 31, 2015 5:45 pm

Re: [how to] enable long touch as right click

Tue Sep 20, 2016 7:14 pm

this bash script emulates a right click on long touch:

Code: Select all

#!/bin/bash

MOUSE_ID=$(xinput --list | grep -i -m 1 'mouse' | grep -o 'id=[0-9]\+' | grep -o '[0-9]\+')#if the script doesn't work comment this line #and exchange every MOUSE_ID with the id of your mouse. to find out the id you can run  xinput --list and look for our mouse #name
next=0
STATE1=$(xinput --query-state MOUSE_ID | grep 'button\[1]' | sort)
while true; do
    sleep 0.2
    STATE2=$(xinput --query-state MOUSE_ID | grep 'button\[1]' | sort)
    var=$(comm -13 <(echo "$STATE1") <(echo "$STATE2"))
    #comm -13 <(echo "$STATE1") <(echo "$STATE2")#uncomment to display click recognition in terminal
    if [[ "$var" == *"button[1]=down"* ]]; then
        if next==6; then
	    xdotool click 3
	    next=0
    	fi
    netxt=$next+1
    else
    	next=0
    fi
    STATE1=$STATE2
done
#$MOUSE_ID
#'button\['
it works for Ubuntu Mate but i don't know if it works for Rasbian.
to run this script on startup just add

Code: Select all

/path/to/this/script
to

Code: Select all

/etc/rc.local

davemunoz
Posts: 6
Joined: Thu Dec 22, 2016 6:07 pm

Re: [how to] enable long touch as right click

Sat Sep 16, 2017 9:15 pm

Hi Folks,
I guess this thread has gone cold but...Did anybody resolve getting right-click emulation working with Jesse?

I did some poking around and tried the suggestions / settings in this thread to no avail.

What I did discover, though, was that when you press and hold the touchscreen, it causes continuous MotionNotify events.

Here's what the single touch looks like from xev:

Code: Select all

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2095440, (39,42), root:(661,344),
    state 0x0, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2095440, (39,42), root:(661,344),
    state 0x0, is_hint 0, same_screen YES

EnterNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x0, time 2095440, (39,42), root:(661,344),
    mode NotifyGrab, detail NotifyInferior, same_screen YES,
    focus YES, state 0

KeymapNotify event, serial 45, synthetic NO, window 0x0,
    keys:  93  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   

LeaveNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x0, time 2095443, (39,42), root:(661,344),
    mode NotifyUngrab, detail NotifyInferior, same_screen YES,
    focus YES, state 0

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2095440, (39,42), root:(661,344),
    state 0x100, is_hint 0, same_screen YES

ButtonPress event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2095440, (39,42), root:(661,344),
    state 0x100, button 1, same_screen YES

EnterNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x0, time 2095443, (39,42), root:(661,344),
    mode NotifyGrab, detail NotifyInferior, same_screen YES,
    focus YES, state 0

KeymapNotify event, serial 45, synthetic NO, window 0x0,
    keys:  93  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2095600, (39,42), root:(661,344),
    state 0x100, is_hint 0, same_screen YES

ButtonRelease event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2095600, (39,42), root:(661,344),
    state 0x100, button 1, same_screen YES

LeaveNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x0, time 2095564, (39,42), root:(661,344),
    mode NotifyUngrab, detail NotifyInferior, same_screen YES,
    focus YES, state 0
Now if I press and hold on the screen, you will see the Button 1 press event followed by continuous motion notify events. I don't think the timeout threshold is ever being reached due to that MotionNotify -- kinda like continually moving the mouse while holding the button.

Code: Select all

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2367610, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

ButtonPress event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2367610, (33,37), root:(655,339),
    state 0x100, button 1, same_screen YES

EnterNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x0, time 2367614, (33,37), root:(655,339),
    mode NotifyGrab, detail NotifyInferior, same_screen YES,
    focus YES, state 0

KeymapNotify event, serial 45, synthetic NO, window 0x0,
    keys:  93  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368530, (32,37), root:(654,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368530, (32,37), root:(654,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368610, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368610, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368650, (32,37), root:(654,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368650, (32,37), root:(654,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368690, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368690, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368730, (32,37), root:(654,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368730, (32,37), root:(654,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368810, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368810, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368890, (32,37), root:(654,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368890, (32,37), root:(654,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368930, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2368930, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

MotionNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2369050, (33,37), root:(655,339),
    state 0x100, is_hint 0, same_screen YES

ButtonRelease event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x1e00002, time 2369050, (33,37), root:(655,339),
    state 0x100, button 1, same_screen YES

LeaveNotify event, serial 45, synthetic NO, window 0x1e00001,
    root 0x25d, subw 0x0, time 2368964, (33,37), root:(655,339),
    mode NotifyUngrab, detail NotifyInferior, same_screen YES,
    focus YES, state 0

I tried playing around with the Threshold settings figuring increasing EmulateThirdButtionMoveThreshold might fix it but alas, still no good.

Code: Select all

Section "InputClass"
        Identifier "evdev touchscreen catchall"
        MatchIsTouchscreen "on"
        MatchDevicePath "/dev/input/event*"
        Driver "evdev"
	Option "EmulateThirdButton" "1"
	Option "EmulateThirdButtonButton" "3"
	Option "EmulateThirdButtonTimeout" "750"
	Option "EmulateThirdButtonMoveThreshold" "30"
EndSection
xinput shows:

Code: Select all

FT5406 memory based driver              	id=6	[slave  pointer  (2)]
	Reporting 4 classes:
		Class originated from: 6. Type: XIButtonClass
		Buttons supported: 5
		Button labels: "Button Unknown" "Button Unknown" "Button Unknown" "Button Wheel Up" "Button Wheel Down"
		Button state:
		Class originated from: 6. Type: XIValuatorClass
		Detail for Valuator 0:
		  Label: Abs MT Position X
		  Range: 0.000000 - 800.000000
		  Resolution: 0 units/m
		  Mode: absolute
		  Current value: 656.000000
		Class originated from: 6. Type: XIValuatorClass
		Detail for Valuator 1:
		  Label: Abs MT Position Y
		  Range: 0.000000 - 480.000000
		  Resolution: 0 units/m
		  Mode: absolute
		  Current value: 340.000000
		Class originated from: 6. Type: XITouchClass
		Touch mode: direct
		Max number of touches: 10
I'm thinking that if we can configure something to not cause the continuous MotionNotify events, things may work better but at this point, I'm not sure how to figure that one out. Anybody know the author for evdev ?

Any thoughts?

Regards,
Dave

davemunoz
Posts: 6
Joined: Thu Dec 22, 2016 6:07 pm

Re: [how to] enable long touch as right click

Sun Sep 17, 2017 4:24 pm

PS: If you're wondering why I don't want to use the twofing solution, it's because of Minecraft -- my daughter is using Minecraft and i think the press-hold method for third button emulation will work better for Minecraft 'drop' operations.

-D

RafaPolit
Posts: 4
Joined: Wed Apr 04, 2018 4:35 am

Re: [how to] enable long touch as right click

Wed Apr 04, 2018 5:42 am

Any news on this front?

I am kind of annoyed that the 'official' instructions would not work with new versions of operating systems. Is no-one updating the instructions? :(

Thanks,
Rafa.

bitter
Posts: 1
Joined: Thu Jun 21, 2018 10:22 am

Re: [how to] enable long touch as right click

Thu Jun 21, 2018 10:30 am

Same problem... last rasbian image... tryed everythink...

But I discovered that... with the parameters in the file related to the touchscreen (I do not know if it makes a difference) chromium easily accepts the "long touch" and it works. I think it's a problem with LXDE, chromium work... desktop NO.

I hope Raspbian team give we a solution (or a way to search for it or a workaround...)

:roll:



.

bedtime
Posts: 30
Joined: Thu Dec 13, 2018 6:02 pm

Re: [how to] enable long touch as right click

Sun Feb 17, 2019 12:45 am

I've taken ahuman's script and fixed up a few things. It's not perfect, but it will do okay if you are in a bind for such a script.

Pros:

1. Added mouse location, so it won't click if the mouse is moved after held down.
2. Added a range variable to set how much distance the mouse may be moved and still be right-clicked.
3. Click will not be triggered if the mouse it moved beyond its range and back to the starting point.
4. Program will only to click once when held down.
5. Changed the script from bash to sh shell to save on resources.
6. Single, double, and triple click with the last click being held should activate the right button, allowing the user to copy highlighted text.
7. Keeping the left button held down beyond having the right click activated will run a custom command (such as clicking the middle mouse button).

Cons:

1. The right click can be activated if the user very very rapidly clicks the mouse in the same spot. I can't see how this would happen if the user were just doing normal computing. Doubling/triple clicking will not trigger this. It can be remedied by shortening the time between click checks but at the expense of cpu.
2. The program uses 1% cpu. The good part is that it will not use any more than 1%, even if the mouse is rapidly clicked or moved around.
3. Just tired atm, but I have to implement a line to say that if the user has held down the left button in the same spot and is using the mouse wheel (to scroll and highlight), then don't right-click. *** EDIT *** No solution found.

rclk.sh:

Code: Select all

#!/bin/sh

# This script requires 'xdotool' to work. 


clicked=0
range=5
count=0
reps=4	#i.e., how long to hold the botton before it clicks?

# If button is held down beyond right click:
overreps=8

# If user continues to keep button held down beyond activating the right click, the middle mouse button will be pressed (useful for highlight/paste):
overcommand="xdotool click --delay 500 3 click 2"	


MOUSE_ID=$(xinput --list | grep -i -m 1 'mouse' | grep -o 'id=[0-9]\+' | grep -o '[0-9]\+')

while : ; do

	sleep .2
 
	STATE2=$(xinput --query-state $MOUSE_ID | grep 'button\[1]')

	mouseXY=$(xdotool getmouselocation)
	mouseX=$(echo $mouseXY | awk '{ print substr($1,3,3) }')
	mouseY=$(echo $mouseXY | awk '{ print substr($2,3,3) }')
    
	if [ $STATE2 = "button[1]=down" ]; then
   
		count=$(($count + 1))				 

		if [ $count -eq 1 ]; then
			prevX=$mouseX;
			prevY=$mouseY;
			echo "Click started @ X: "$prevX" Y: "$prevY
		fi 


		if [ $mouseX -lt $(($prevX + $range)) ] && [ $mouseX -gt $(($prevX - $range)) ] && [ $mouseY -lt $(($prevY + $range)) ] && [ $mouseY -gt $(($prevY - $range)) ]; then

			if [ $count -eq $reps ] && [ $clicked -eq 0 ] ; then
				clicked=1
				xdotool click 3
				echo "Right Click activated!"
			fi


			if [ $count -eq $overreps ]; then echo "OVER CLICK!"; $overcommand; fi



		else
			if [ $clicked -eq 0 ]; then echo "You moved the mouse!"; fi
			clicked=1	
		fi

    

	else
		count=0;
		clicked=0
	fi

	STATE1=$STATE2

done

*** EDIT ***

Been using it for a whole day of intensive computing and not a single misfire yet. :)

bedtime
Posts: 30
Joined: Thu Dec 13, 2018 6:02 pm

Re: [how to] enable long touch as right click

Tue Feb 26, 2019 11:43 pm

Here's a C++ implementation of the hold-to-right-click program:

Pros:

1. Uses almost nil CPU when inactive and >.3% when working hardest. Memory footprint is extremely small (> 1mb ?).
2. Self-contained and needs no extra programs to run. No need for xdotools.
3. Much better timer; it can be set to trigger the right button at any time.
4. The clicking mechanism cannot be defeated or false-clicked by repeated clicking. As far as I can tell on my machine, there are no ways to defeat it.
5. If the button (or touchscreen) is held down longer, it can do right-click-hold, holding the right button until the left is pressed again (or the touchscreen let go and tapped again). This makes resizing and other such things possible.
6. When highlighting + scrolling in one spot with the mouse wheel, the right-click will automatically be disabled until the highlighting is completed.
7. Can be used with/without a mouse or touchscreen with no alteration needed.
8. No bugs that I am aware of after extensive full-time mouse use.

Cons:

1. Although designed for a touchscreen, I've yet to be able to test it on one. If anyone does try it, please let me know. In a few weeks, I'll have my official RPI screen, so I'll update you all.
2. No error protection whatsoever.
3. All is hard-coded. Why? Because, like the crew over at suckless, I prefer my programs to stay small, fast, and efficient.


mouse.cpp:

Code: Select all

/*
        Secondary Button Mouse stimulator


 Compile with:

 g++ -Wall -Ofast mouse.cpp -o mouse -lX11 -lXtst -lXext


*/

#include <fcntl.h>
#include <iostream>
#include <linux/input.h>
#include <string.h> 
#include <unistd.h>
#include <X11/extensions/XTest.h>

#define MOUSEFILE "/dev/input/event0"

int main()
{

    Display *dpy = NULL;
    XEvent event;
    dpy = XOpenDisplay(NULL);

    int fd;
    struct input_event ie;
    Window root, child;
    int rootX, rootY, winX, winY;
    unsigned int mask;
    XQueryPointer(dpy,DefaultRootWindow(dpy),&root,&child,&rootX,&rootY,&winX,&winY,&mask);


    if((fd = open(MOUSEFILE, O_RDONLY)) == -1) {
        perror("opening device");
        exit(EXIT_FAILURE);
    }

    bool scrolling = false;  // Cancel if user is scrolling with wheel
    bool hold = false;
    auto time_start_sec      = ie.time.tv_sec;
    auto time_stop_sec       = ie.time.tv_sec;
    auto time_start_usec     = ie.time.tv_usec;
    auto time_stop_usec      = ie.time.tv_usec;
    auto time_stop_usec_adj  = ie.time.tv_usec;
    auto time_real           = ie.time.tv_usec;
    float time_elapsed_adj;
    float time_to_click      = 0.4; // How long to hold the button down?
    float time_to_hold       = 1.2; // Time pressed for holding click
    short startX =  0;       // Mouse location (cancel click if moved)
    short stopX  =  0;
    short startY =  0;
    short stopY  =  0;
    short range =  10;       // How much can mouse move whilst clicking?


    std::cout << "Ready for mouse events..." << std::endl;

    while(true){

        // Grab mouse events:
        read(fd, &ie, sizeof(struct input_event));

        if (ie.type == 2) {
            if (ie.code == 8 ){
                std::cout << "Other button pressed!" << std::endl;
                scrolling=true;
            }

            if (ie.code == 0) { rootX += ie.value;
            }else if (ie.code == 1) { rootY += ie.value; }
            } else if (ie.type == 1) {
                if (ie.code == 272 ) {
 
                if (ie.value == 0) {

                // Timer from mouse events is used
                time_real      = ie.time.tv_sec;
                time_stop_sec  = time_real - time_start_sec ;
                time_stop_usec = ie.time.tv_usec;

                if (time_stop_usec < time_start_usec){

                    time_stop_usec_adj = time_stop_usec + (1000000 - time_start_usec);
                    if (time_real - time_start_sec > 0 )
                        time_stop_sec = time_stop_sec - 1;

                }else
                    time_stop_usec_adj = time_stop_usec - time_start_usec;

                time_elapsed_adj = float(time_stop_sec) + (float(time_stop_usec_adj) / 1000000);
                stopX = rootX;
                stopY = rootY;

                std::cout << "Released @ X: " << stopX << " Y: " << stopY << " Time held: " << time_elapsed_adj << " seconds." << std::endl;	


                if (time_elapsed_adj >= time_to_click){

                    if (stopX <= (startX + range) && stopX >= (startX - range) && stopY <= (startY + range) && stopY >= (startY - range) && scrolling == false)
                    {

                        std::cout << "Clicked!" << std::endl;
 
                        if(time_elapsed_adj >= time_to_hold)
                        {

                            std::cout << "Activating Hold!" << std::endl;
                            
                            XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);
 
                            usleep(1000);

                            XTestFakeButtonEvent (dpy, 3, True,  CurrentTime);
                            usleep(1000);

                            XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                            hold = true;

                        }else{

                            std::cout << "Activating Click!" << std::endl;
                            XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                            usleep(1000);

                            XTestFakeButtonEvent (dpy, 3, True,  CurrentTime);
                            usleep(1000);

                            XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                            usleep(1000);

                            XTestFakeButtonEvent (dpy, 3, False, CurrentTime);
                            usleep(1000);
XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                        }
                    }
                }
            }

            // Mouse button is 'clicked' (initial press):
            if (ie.value == 1)  {

                scrolling = false;
                startX = rootX;
                startY = rootY; 
                time_start_sec  = ie.time.tv_sec;
                time_start_usec = ie.time.tv_usec;
                std::cout << "\nPressed  @ X: " << startX << " Y: "<< startY << std::endl;

                // Left-clicking cancels the hold:
                if (hold){
                    std::cout << "Cancelling hold!" << std::endl;

                    XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                        &event.xbutton.window, &event.xbutton.x_root,
                        &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                        &event.xbutton.state);

                    usleep(1000);

                    XTestFakeButtonEvent (dpy, 3, False,  CurrentTime);

                    usleep(1000);

                    XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                        &event.xbutton.window, &event.xbutton.x_root,
                        &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                        &event.xbutton.state);
                }

                hold = false;
            }
        } 
    }
	
}

    XCloseDisplay (dpy);

    return 0;

}

Code is on github:
https://gist.github.com/bathtime/f92d81 ... cac00313ec

Feel free to fork, modify, and have fun with. :)

**** EDIT ****

Having tested the above code on my tablet screen (the official RPi 7" screen), I found that it doesn't work at all with touch. I found the tablet parameters and was able to make it work for touch screens now.

The code below still needs working on. Press the screen for .4 seconds for a right clic and 1.5 seconds for middle click.

mouse.cpp;

Code: Select all

/*
        Secondary Button Mouse stimulator

 Compile with:

 g++ -Wall -Ofast mouse.cpp -o mouse -lX11 -lXtst -lXext

*/

#include <fcntl.h>
#include <iostream>
#include <linux/input.h>
#include <string> 
#include <unistd.h>
#include <X11/extensions/XTest.h>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <array>
#include<fstream>
#include<iostream>

int main() {


    const char* eventFile;

    Display *dpy = NULL;
    XEvent event;
    dpy = XOpenDisplay(NULL);

    int fd;
    struct input_event ie;
    Window root, child;
    int rootX, rootY, winX, winY;
    unsigned int mask;
    XQueryPointer(dpy,DefaultRootWindow(dpy),&root,&child,&rootX,&rootY,&winX,&winY,&mask);

    std::array<char, 128> buffer;
    std::string result;

    FILE* pipe = popen("cat /proc/bus/input/devices | awk -v x='FT5406' '$0~x,EOF' | awk '/Handler/ {print $3; exit}'", "r");

    if (!pipe)
    {
        std::cerr << "Couldn't start command." << std::endl;
        return 1;
    }
    while (fgets(buffer.data(), 128, pipe) != NULL)
        result += buffer.data();
    pclose(pipe);

    result = "/dev/input/" + result.substr(0, result.length() - 1); 
   
    std::cout << "Using file:" << result << std::endl;

    eventFile = result.c_str();

        if((fd = open(eventFile, O_RDONLY)) == -1) {
            perror("opening device");
            return 1; 
        }


    auto time_start_sec      = ie.time.tv_sec;
    auto time_stop_sec       = ie.time.tv_sec;
    auto time_start_usec     = ie.time.tv_usec;
    auto time_stop_usec      = ie.time.tv_usec;
    auto time_stop_usec_adj  = ie.time.tv_usec;
    auto time_real           = ie.time.tv_usec;
    float time_elapsed_adj;
    float time_to_click      = .4; // How long to hold the button down?
    float time_to_hold       = 1.5; // Time pressed for holding click

    std::cout << "Ready for mouse events..." << std::endl;

    while(true){

        // Grab mouse events:
        read(fd, &ie, sizeof(struct input_event));


    //    std::cout << "Type: " << ie.type << " Code: " << ie.code << " Value: " << ie.value << " Time: " << ie.time.tv_sec << "." << ie.time.tv_usec << std::endl;

            if (ie.type == 1 && ie.code == 330 && ie.value == 0) {

                // Timer from mouse events is used
                time_real      = ie.time.tv_sec;
                time_stop_sec  = time_real - time_start_sec ;
                time_stop_usec = ie.time.tv_usec;

                if (time_stop_usec < time_start_usec){

                    time_stop_usec_adj = time_stop_usec + (1000000 - time_start_usec);
                    if (time_real - time_start_sec > 0 )
                        time_stop_sec = time_stop_sec - 1;

                }else
                    time_stop_usec_adj = time_stop_usec - time_start_usec;

                time_elapsed_adj = float(time_stop_sec) + (float(time_stop_usec_adj) / 1000000);

//                std::cout << "Released! ...  Time held: " << time_elapsed_adj << " seconds." << " Time: " << time_real << "." << time_stop_usec << std::endl;	

                if (time_elapsed_adj >= time_to_click){
 
                        if(time_elapsed_adj >= time_to_hold)
                        {

                            std::cout << "Middle button clicked!" << std::endl;
                            XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                            usleep(1000);

                            XTestFakeButtonEvent (dpy, 2, True,  CurrentTime);
                            usleep(1000);

                            XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                            usleep(1000);

                            XTestFakeButtonEvent (dpy, 2, False, CurrentTime);
                            usleep(1000);
XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                        }else{

                            std::cout << "Right button clicked!" << std::endl;
                            XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                            usleep(1000);

                            XTestFakeButtonEvent (dpy, 3, True,  CurrentTime);
                            usleep(1000);

                            XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                            usleep(1000);

                            XTestFakeButtonEvent (dpy, 3, False, CurrentTime);
                            usleep(1000);
XQueryPointer (dpy, RootWindow (dpy, 0), &event.xbutton.root,
                                  &event.xbutton.window, &event.xbutton.x_root,
                                  &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
                                  &event.xbutton.state);

                         }
    }

}

                 
             // Mouse button is 'clicked' (initial press):

            if (ie.type == 0 && ie.code == 0 && ie.value == 0){ 

            //if ((ie.type == 0 || ie.type == 3) && ie.value > -1 )  {

                time_start_sec  = ie.time.tv_sec;
                time_start_usec = ie.time.tv_usec;
                //std::cout << "\nPressed! ...  Time: " << time_start_sec << "." << time_start_usec << std::endl;

            }

    }
	

    XCloseDisplay (dpy);

    return 0;

}
I admit the code is a little messy; I'm a trifle burnt out atm.

Return to “Official Foundation Display”