Added tapioca
This commit is contained in:
Executable
+309
@@ -0,0 +1,309 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import evdev
|
||||
import subprocess
|
||||
from decimal import Decimal
|
||||
import time
|
||||
import os
|
||||
import ConfigParser
|
||||
from collections import OrderedDict
|
||||
from threading import Timer, Thread
|
||||
from pymouse import PyMouse
|
||||
import argparse
|
||||
import sys
|
||||
import math
|
||||
|
||||
# todo
|
||||
# long press should not work on two finger long press
|
||||
# implement three finger tap
|
||||
# implement swipes
|
||||
|
||||
mouse = PyMouse()
|
||||
app_name = "tapioca"
|
||||
config_folder = os.path.join(os.path.expanduser("~"), '.config', app_name)
|
||||
config_file = app_name + ".conf"
|
||||
full_config_file_path = os.path.join(config_folder, config_file)
|
||||
Config = ConfigParser.ConfigParser(allow_no_value=True)
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=app_name + " enables right click on linux touchscreen devices.")
|
||||
parser.add_argument(
|
||||
"--device", help="Specify name of your touch panel make" \
|
||||
" (can be found out by running xinput command).")
|
||||
|
||||
args = parser.parse_args()
|
||||
# print(args.device)
|
||||
|
||||
# do not edit these settings, all settings should be changed in .conf file
|
||||
# in user section
|
||||
|
||||
default_section = "Default Settings"
|
||||
user_section = "User Settings"
|
||||
default_settings = OrderedDict([
|
||||
('; Touch panel make (run xinput command in terminal)', None),
|
||||
('touch_panel', ""),
|
||||
('; Minimum long press time in seconds, e.g - 0.5, 1.2', None),
|
||||
('minimum_long_press_time', 1.5),
|
||||
('; Right click methods, possible values - xdotool, pymouse', None),
|
||||
('right_click_method', 'xdotool'),
|
||||
('; Long press behavior, possible values - pc (menu appears after finger lift),' \
|
||||
' smartphone (no finger lift required, menu flickers once)', None),
|
||||
('long_press_behavior', 'pc'),
|
||||
('; Long press, possible values - 1 (True), 0 (False)', None),
|
||||
('enable_long_press', 1),
|
||||
('; Two finger tap, possible values - 1 (True), 0 (False)', None),
|
||||
('enable_two_finger_tap', 1)
|
||||
])
|
||||
|
||||
def setconfig():
|
||||
try:
|
||||
if os.stat(full_config_file_path).st_size > 0:
|
||||
file_empty = False
|
||||
else:
|
||||
file_empty = True
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if not os.path.exists(config_folder):
|
||||
os.makedirs(config_folder)
|
||||
if not os.path.exists(full_config_file_path) or file_empty == True:
|
||||
with open(full_config_file_path, "w+") as f:
|
||||
Config.add_section(default_section)
|
||||
Config.set(
|
||||
default_section, '; !!!! do not edit, change settings in user section !!!!')
|
||||
for k, v in default_settings.items():
|
||||
if v == None:
|
||||
Config.set(default_section, k)
|
||||
else:
|
||||
Config.set(default_section, k, v)
|
||||
Config.add_section(user_section)
|
||||
Config.set(user_section, '; change settings below')
|
||||
for k, v in default_settings.items():
|
||||
if v == None:
|
||||
Config.set(user_section, k)
|
||||
else:
|
||||
Config.set(user_section, k, v)
|
||||
Config.write(f)
|
||||
|
||||
if args.device != None:
|
||||
with open(full_config_file_path, "w") as b:
|
||||
Config.set(user_section, "touch_panel", args.device)
|
||||
Config.write(b)
|
||||
|
||||
try:
|
||||
setconfig()
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
|
||||
Config.read(full_config_file_path)
|
||||
|
||||
try:
|
||||
touch_panel = Config.get(user_section, "touch_panel")
|
||||
except:
|
||||
try:
|
||||
touch_panel = Config.get(default_section, "touch_panel")
|
||||
except:
|
||||
touch_panel = default_settings['touch_panel']
|
||||
|
||||
try:
|
||||
minimum_long_press_time = float(Config.get(
|
||||
user_section, "minimum_long_press_time"))
|
||||
except:
|
||||
try:
|
||||
minimum_long_press_time = float(Config.get(
|
||||
default_section, "minimum_long_press_time"))
|
||||
except:
|
||||
minimum_long_press_time = default_settings['minimum_long_press_time']
|
||||
|
||||
try:
|
||||
right_click_method = Config.get(user_section, "right_click_method")
|
||||
except:
|
||||
try:
|
||||
right_click_method = Config.get(default_section, "right_click_method")
|
||||
except:
|
||||
right_click_method = default_settings['right_click_method']
|
||||
|
||||
try:
|
||||
long_press_behavior = Config.get(user_section, "long_press_behavior")
|
||||
except:
|
||||
try:
|
||||
long_press_behavior = Config.get(
|
||||
default_section, "long_press_behavior")
|
||||
except:
|
||||
long_press_behavior = default_settings['long_press_behavior']
|
||||
|
||||
try:
|
||||
enable_long_press = Config.getboolean(user_section, "enable_long_press")
|
||||
except:
|
||||
try:
|
||||
enable_long_press = Config.getboolean(
|
||||
default_section, "enable_long_press")
|
||||
except:
|
||||
enable_long_press = default_settings['enable_long_press']
|
||||
|
||||
try:
|
||||
enable_two_finger_tap = Config.getboolean(
|
||||
user_section, "enable_two_finger_tap")
|
||||
except:
|
||||
try:
|
||||
enable_two_finger_tap = Config.getboolean(
|
||||
default_section, "enable_two_finger_tap")
|
||||
except:
|
||||
enable_two_finger_tap = default_settings['enable_two_finger_tap']
|
||||
|
||||
lift_time = None
|
||||
touch_time = None
|
||||
touch_x = 0
|
||||
touch_y = 0
|
||||
finger0_time = None
|
||||
finger1_time = None
|
||||
finger2_time = None
|
||||
abs_touch_time = None
|
||||
abs_lift_time = None
|
||||
no_device_found = True
|
||||
long_press_done = False
|
||||
|
||||
dev_abs_x = 0
|
||||
dev_abs_y = 0
|
||||
|
||||
def rclick():
|
||||
if right_click_method == "xdotool":
|
||||
# proc = subprocess.Popen("eval $(xdotool getmouselocation --shell) && echo $X $Y", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell = True ).communicate()
|
||||
# print proc[0]
|
||||
# p = proc[0].strip('\n')
|
||||
# xc = int(p.partition(' ')[0])
|
||||
# yc = int(p.partition(' ')[2])
|
||||
# print xc, yc
|
||||
# subprocess.Popen(["xdotool", "mousemove", "--sync", str(xc), str(yc)], shell = False)
|
||||
subprocess.Popen(["xdotool", "click", "3"], stdout=subprocess.PIPE)
|
||||
elif right_click_method == "pymouse":
|
||||
mouse.click(mouse.position()[0], mouse.position()[1], 2)
|
||||
|
||||
def dummy(time):
|
||||
pass
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()]
|
||||
|
||||
for device in devices:
|
||||
# print(device.fn, device.name, device.phys)
|
||||
# print device.name
|
||||
if (device.name == touch_panel):
|
||||
input_node = device.fn
|
||||
no_device_found = False
|
||||
|
||||
if no_device_found == True:
|
||||
print "No touch input detected."
|
||||
print "Please make sure you have entered correct touch panel name in user settings."
|
||||
print "Quitting in 10 seconds."
|
||||
time.sleep(10)
|
||||
quit()
|
||||
|
||||
device = evdev.InputDevice(input_node)
|
||||
# print device
|
||||
# print device.capabilities(verbose=True)
|
||||
# print device.active_keys(verbose=True)
|
||||
|
||||
for event in device.read_loop():
|
||||
try:
|
||||
# print(evdev.util.categorize(event))
|
||||
if event.type == 3: # absolute axis event
|
||||
if event.code == 0:
|
||||
dev_abs_x = event.value
|
||||
elif event.code == 1:
|
||||
dev_abs_y = event.value
|
||||
elif event.type == 1: # key event
|
||||
#print(evdev.util.categorize(event))
|
||||
#print event.code
|
||||
pass
|
||||
else:
|
||||
#print(evdev.util.categorize(event))
|
||||
#print event.type
|
||||
pass
|
||||
|
||||
if event.code == 321 and event.value == 0:
|
||||
print "stylus tool rubber click"
|
||||
rclick()
|
||||
|
||||
if event.code == 330 and event.value == 1:
|
||||
touch_time = Decimal(str(event.sec) + "." + str(event.usec))
|
||||
touch_x = dev_abs_x
|
||||
touch_y = dev_abs_y
|
||||
# print touch_time, " (", touch_x, ", ", touch_y, ")"
|
||||
t = Timer(minimum_long_press_time, dummy, [touch_time])
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
if event.code == 330 and event.value == 0:
|
||||
lift_time = Decimal(str(event.sec) + "." + str(event.usec))
|
||||
# print lift_time
|
||||
else:
|
||||
lift_time = None
|
||||
|
||||
if event.code == 47 and event.value == 0:
|
||||
finger0_time = Decimal(str(event.sec) + "." + str(event.usec))
|
||||
# print finger0_time
|
||||
|
||||
if event.code == 47 and event.value == 1:
|
||||
finger1_time = Decimal(str(event.sec) + "." + str(event.usec))
|
||||
# print finger1_time
|
||||
|
||||
if event.code == 47 and event.value == 2:
|
||||
finger2_time = Decimal(str(event.sec) + "." + str(event.usec))
|
||||
# print finger2_time
|
||||
|
||||
if event.code == 57 and event.value > -1:
|
||||
abs_touch_time = Decimal(str(event.sec) + "." + str(event.usec))
|
||||
# print abs_touch_time
|
||||
t = Timer(minimum_long_press_time, dummy, [abs_touch_time])
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
if event.code == 57 and event.value == -1:
|
||||
abs_lift_time = Decimal(str(event.sec) + "." + str(event.usec))
|
||||
# print abs_lift_time
|
||||
else:
|
||||
abs_lift_time = None
|
||||
|
||||
if touch_time != None and lift_time == None and long_press_behavior == "smartphone":
|
||||
if t.is_alive() == False and long_press_done == False:
|
||||
if enable_long_press == True:
|
||||
touch_distance = math.sqrt((touch_x-dev_abs_x)**2+(touch_y-dev_abs_y)**2)
|
||||
# print "touch distance: ", touch_distance
|
||||
if touch_distance < 200:
|
||||
print "smartphone long press"
|
||||
rclick()
|
||||
long_press_done = True
|
||||
t.cancel()
|
||||
t.join()
|
||||
|
||||
if touch_time != None and lift_time != None and enable_long_press == True:
|
||||
diff = lift_time - touch_time
|
||||
# print diff
|
||||
if diff >= minimum_long_press_time and long_press_behavior == "pc":
|
||||
print "pc long press"
|
||||
rclick()
|
||||
|
||||
if event.code == 330 and event.value == 0:
|
||||
if long_press_done == True and long_press_behavior == "smartphone":
|
||||
rclick()
|
||||
long_press_done = False
|
||||
touch_time = None
|
||||
|
||||
if finger0_time != None and finger1_time != None and enable_two_finger_tap == True:
|
||||
if event.code == 330 and event.value == 0:
|
||||
if finger0_time == finger1_time:
|
||||
print "Two finger tap"
|
||||
rclick()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pass
|
||||
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user