Proof of concept script to disable the touchpad while typing
#1
I've just quickly made the following script for python, only tested with python3, on the stock Mate pinebook install.
Not sure if other installs move around the xinput device for the touchpad (else replace the 8 with the right number)

This script disables the touchpad of the pinebook for 0.5 second whenever a key is pressed, any key, including ctrl/shift/alt/mod.  So it's not perfect and cannot be use for shift/ctrl+click very effectively yet. But the script could be modified for that.

Note that if you google for the touchpad problem, you will find a lot of mentions for "syndaemon", which doesn't work (and exits without a message) The "synclient" command however will tell you why, because our touchpad isn't showing up as a touchpad but as an emulated mouse.
Hench this hacky script.

And I've just typed this post without a single problem while the script is running. Figured I share this ASAP, as the very sensitive touch pad is at the top of the list of things that people find annoying.

Code:
import threading import time import os class TouchpadHack:     def __init__(self):         self.__disabled = False         self.__condition = threading.Condition()         self.__disabled_until_time = time.monotonic()                  threading.Thread(target=self.timeoutThread).start()          def timeoutThread(self):         while True:             with self.__condition:                 self.__condition.wait()             os.system("xinput disable 8")             print("disable")             while time.monotonic() < self.__disabled_until_time:                 time.sleep(self.__disabled_until_time - time.monotonic())             os.system("xinput enable 8")             print("enable")     def inputReadThread(self):         f = open("/dev/input/event2", "rb")         while True:             # We read events here from the keyboard and then just ignore them.             # The only thing we care about is that an event happens.             event = f.read(100)             with self.__condition:                 self.__condition.notify()                 self.__disabled_until_time = time.monotonic() + 0.5 TouchpadHack().inputReadThread()
#2
Will make sure to try it out first thing tomorrow and relay feedback.
You can find me on IRC, Discord and Twitter


#3
With the stuff I had laying around from a different project, I enhanced it a bit, it's a bit more complex now, but it should allow shift/ctrl/alt + click now. And be better protected against different order of hardware initialization.


Code:
import threading import time import os import struct import fcntl import subprocess # ioctl to get the device name of /dev/input/event* EVIOCGNAME = 0x82004506 EVIOCGBIT = 0x81fe4520 # Format for the linux /dev/input/event* events. #   tv_sec, tv_usec, type, code, value EVENT_FMT = "llHHi" EV_SYN = 0x00 EV_KEY = 0x01 EV_REL = 0x02 EV_ABS = 0x03 EV_MSC = 0x04 EV_SW  = 0x05 EV_LED = 0x11 EV_SND = 0x12 EV_REP = 0x14 EV_FF  = 0x15 EV_PWR = 0x16 EV_FF_STATUS = 0x17 KEY_RESERVED = 0 KEY_ESC = 1 KEY_1 = 2 KEY_2 = 3 KEY_3 = 4 KEY_4 = 5 KEY_5 = 6 KEY_6 = 7 KEY_7 = 8 KEY_8 = 9 KEY_9 = 10 KEY_0 = 11 KEY_MINUS = 12 KEY_EQUAL = 13 KEY_BACKSPACE = 14 KEY_TAB = 15 KEY_Q = 16 KEY_W = 17 KEY_E = 18 KEY_R = 19 KEY_T = 20 KEY_Y = 21 KEY_U = 22 KEY_I = 23 KEY_O = 24 KEY_P = 25 KEY_LEFTBRACE = 26 KEY_RIGHTBRACE = 27 KEY_ENTER = 28 KEY_LEFTCTRL = 29 KEY_A = 30 KEY_S = 31 KEY_D = 32 KEY_F = 33 KEY_G = 34 KEY_H = 35 KEY_J = 36 KEY_K = 37 KEY_L = 38 KEY_SEMICOLON = 39 KEY_APOSTROPHE = 40 KEY_GRAVE = 41 KEY_LEFTSHIFT = 42 KEY_BACKSLASH = 43 KEY_Z = 44 KEY_X = 45 KEY_C = 46 KEY_V = 47 KEY_B = 48 KEY_N = 49 KEY_M = 50 KEY_COMMA = 51 KEY_DOT = 52 KEY_SLASH = 53 KEY_RIGHTSHIFT = 54 KEY_KPASTERISK = 55 KEY_LEFTALT = 56 KEY_SPACE = 57 KEY_CAPSLOCK = 58 KEY_F1 = 59 KEY_F2 = 60 KEY_F3 = 61 KEY_F4 = 62 KEY_F5 = 63 KEY_F6 = 64 KEY_F7 = 65 KEY_F8 = 66 KEY_F9 = 67 KEY_F10 = 68 KEY_NUMLOCK = 69 KEY_SCROLLLOCK = 70 KEY_KP7 = 71 KEY_KP8 = 72 KEY_KP9 = 73 KEY_KPMINUS = 74 KEY_KP4 = 75 KEY_KP5 = 76 KEY_KP6 = 77 KEY_KPPLUS = 78 KEY_KP1 = 79 KEY_KP2 = 80 KEY_KP3 = 81 KEY_KP0 = 82 KEY_KPDOT = 83 KEY_ZENKAKUHANKAKU = 85 KEY_102ND = 86 KEY_F11 = 87 KEY_F12 = 88 KEY_RO = 89 KEY_KATAKANA = 90 KEY_HIRAGANA = 91 KEY_HENKAN = 92 KEY_KATAKANAHIRAGANA = 93 KEY_MUHENKAN = 94 KEY_KPJPCOMMA = 95 KEY_KPENTER = 96 KEY_RIGHTCTRL = 97 KEY_KPSLASH = 98 KEY_SYSRQ = 99 KEY_RIGHTALT = 100 KEY_LINEFEED = 101 KEY_HOME = 102 KEY_UP = 103 KEY_PAGEUP = 104 KEY_LEFT = 105 KEY_RIGHT = 106 KEY_END = 107 KEY_DOWN = 108 KEY_PAGEDOWN = 109 KEY_INSERT = 110 KEY_DELETE = 111 KEY_MACRO = 112 KEY_MUTE = 113 KEY_VOLUMEDOWN = 114 KEY_VOLUMEUP = 115 KEY_POWER = 116 # SC System Power Down KEY_KPEQUAL = 117 KEY_KPPLUSMINUS = 118 KEY_PAUSE = 119 KEY_SCALE = 120 # AL Compiz Scale (Expose) KEY_KPCOMMA = 121 KEY_HANGEUL = 122 KEY_HANGUEL = KEY_HANGEUL KEY_HANJA = 123 KEY_YEN = 124 KEY_LEFTMETA = 125 KEY_RIGHTMETA = 126 KEY_COMPOSE = 127 KEY_STOP = 128 # AC Stop KEY_AGAIN = 129 KEY_PROPS = 130 # AC Properties KEY_UNDO = 131 # AC Undo KEY_FRONT = 132 KEY_COPY = 133 # AC Copy KEY_OPEN = 134 # AC Open KEY_PASTE = 135 # AC Paste KEY_FIND = 136 # AC Search KEY_CUT = 137 # AC Cut KEY_HELP = 138 # AL Integrated Help Center KEY_MENU = 139 # Menu (show menu) KEY_CALC = 140 # AL Calculator KEY_SETUP = 141 KEY_SLEEP = 142 # SC System Sleep KEY_WAKEUP = 143 # System Wake Up KEY_FILE = 144 # AL Local Machine Browser KEY_SENDFILE = 145 KEY_DELETEFILE = 146 KEY_XFER = 147 KEY_PROG1 = 148 KEY_PROG2 = 149 KEY_WWW = 150 # AL Internet Browser KEY_MSDOS = 151 KEY_COFFEE = 152 # AL Terminal Lock/Screensaver KEY_SCREENLOCK = KEY_COFFEE KEY_ROTATE_DISPLAY = 153 # Display orientation for e.g. tablets KEY_DIRECTION = KEY_ROTATE_DISPLAY KEY_CYCLEWINDOWS = 154 KEY_MAIL = 155 KEY_BOOKMARKS = 156 # AC Bookmarks KEY_COMPUTER = 157 KEY_BACK = 158 # AC Back KEY_FORWARD = 159 # AC Forward KEY_CLOSECD = 160 KEY_EJECTCD = 161 KEY_EJECTCLOSECD = 162 KEY_NEXTSONG = 163 KEY_PLAYPAUSE = 164 KEY_PREVIOUSSONG = 165 KEY_STOPCD = 166 KEY_RECORD = 167 KEY_REWIND = 168 KEY_PHONE = 169 # Media Select Telephone KEY_ISO = 170 KEY_CONFIG = 171 # AL Consumer Control Configuration KEY_HOMEPAGE = 172 # AC Home KEY_REFRESH = 173 # AC Refresh KEY_EXIT = 174 # AC Exit KEY_MOVE = 175 KEY_EDIT = 176 KEY_SCROLLUP = 177 KEY_SCROLLDOWN = 178 KEY_KPLEFTPAREN = 179 KEY_KPRIGHTPAREN = 180 KEY_NEW = 181 # AC New KEY_REDO = 182 # AC Redo/Repeat KEY_F13 = 183 KEY_F14 = 184 KEY_F15 = 185 KEY_F16 = 186 KEY_F17 = 187 KEY_F18 = 188 KEY_F19 = 189 KEY_F20 = 190 KEY_F21 = 191 KEY_F22 = 192 KEY_F23 = 193 KEY_F24 = 194 KEY_PLAYCD = 200 KEY_PAUSECD = 201 KEY_PROG3 = 202 KEY_PROG4 = 203 KEY_DASHBOARD = 204 # AL Dashboard KEY_SUSPEND = 205 KEY_CLOSE = 206 # AC Close KEY_PLAY = 207 KEY_FASTFORWARD = 208 KEY_BASSBOOST = 209 KEY_PRINT = 210 # AC Print KEY_HP = 211 KEY_CAMERA = 212 KEY_SOUND = 213 KEY_QUESTION = 214 KEY_EMAIL = 215 KEY_CHAT = 216 KEY_SEARCH = 217 KEY_CONNECT = 218 KEY_FINANCE = 219 # AL Checkbook/Finance KEY_SPORT = 220 KEY_SHOP = 221 KEY_ALTERASE = 222 KEY_CANCEL = 223 # AC Cancel KEY_BRIGHTNESSDOWN = 224 KEY_BRIGHTNESSUP = 225 KEY_MEDIA = 226 KEY_SWITCHVIDEOMODE = 227 # Cycle between available video outputs (Monitor/LCD/TV-out/etc) KEY_KBDILLUMTOGGLE = 228 KEY_KBDILLUMDOWN = 229 KEY_KBDILLUMUP = 230 KEY_SEND = 231 # AC Send KEY_REPLY = 232 # AC Reply KEY_FORWARDMAIL = 233 # AC Forward Msg KEY_SAVE = 234 # AC Save KEY_DOCUMENTS = 235 KEY_BATTERY = 236 KEY_BLUETOOTH = 237 KEY_WLAN = 238 KEY_UWB = 239 KEY_UNKNOWN = 240 KEY_VIDEO_NEXT = 241 # drive next video source KEY_VIDEO_PREV = 242 # drive previous video source KEY_BRIGHTNESS_CYCLE = 243 # brightness up, after max is min KEY_BRIGHTNESS_AUTO = 244 # Set Auto Brightness: manual, brightness control is off, rely on ambient KEY_BRIGHTNESS_ZERO = KEY_BRIGHTNESS_AUTO KEY_DISPLAY_OFF = 245 # display device to off state KEY_WWAN = 246 # Wireless WAN (LTE, UMTS, GSM, etc.) KEY_WIMAX = KEY_WWAN KEY_RFKILL = 247 # Key that controls all radios KEY_MICMUTE = 248 # Mute / unmute the microphone class TouchpadHack:    def __init__(self):        self.__disabled = False        self.__condition = threading.Condition()        self.__disabled_until_time = time.monotonic()        self.__running = True                self.__disable_timeout = 0.5        self.__timeout_thread = threading.Thread(target=self.timeoutThread, daemon=True)    def findXInputDeviceNumber(self):        res = subprocess.run(["/usr/bin/xinput", "list"], stdout=subprocess.PIPE).stdout        for line in res.split(b"\n"):            if b"pointer" in line and b"HAILUCK" in line:                line = line[line.find(b"id=")+3:]                line = line[:line.find(b"\t")]                return int(line)        return None        def timeoutThread(self):        device_number = self.findXInputDeviceNumber()        while self.__running:            with self.__condition:                self.__condition.wait()            os.system("xinput disable %d" % (device_number))            print("disable")            while time.monotonic() < self.__disabled_until_time and self.__running:                time.sleep(self.__disabled_until_time - time.monotonic())            os.system("xinput enable %d" % (device_number))            print("enable")    def inputReadThread(self):        self.__timeout_thread.start()        # Search for the first Pinebook keyboard entry. The first seems to be the keyboard, the 2nd the mouse.        for event_path in sorted(os.listdir("/dev/input")):            if not event_path.startswith("event"):                continue            event_path = os.path.join("/dev/input", event_path)            f = open(event_path, "rb")            input_device_name = bytearray(512)            fcntl.ioctl(f, EVIOCGNAME, input_device_name, True)            input_device_name = input_device_name[:input_device_name.find(b"\0")].decode("utf-8")            if input_device_name == "HAILUCK CO.,LTD USB KEYBOARD":                break            f.close()        try:            while True:                # We read events here from the keyboard and then just ignore them.                # The only thing we care about is that an event happens.                event = f.read(struct.calcsize(EVENT_FMT))                tv_sec, tv_usec, etype, code, value = struct.unpack(EVENT_FMT, event)                if etype == EV_KEY and self.isDisableKey(code):                    self.initiateOrUpdateDisable()        except KeyboardInterrupt:            self.__running = False            print("Shutting down")        with self.__condition:            self.__condition.notify()        self.__timeout_thread.join()    def isDisableKey(self, code):        # Don't react to modifier keys        if code == KEY_LEFTALT or code == KEY_RIGHTALT:            return False        if code == KEY_LEFTCTRL or code == KEY_RIGHTCTRL:            return False        if code == KEY_LEFTSHIFT or code == KEY_RIGHTSHIFT:            return False        if code == KEY_LEFTMETA or code == KEY_RIGHTMETA:            return False        return True    def initiateOrUpdateDisable(self):        with self.__condition:            self.__condition.notify()            self.__disabled_until_time = time.monotonic() + self.__disable_timeout TouchpadHack().inputReadThread()
#4
This is really great!!!

I'm able to type without triggering nearly as many stray clicks now.

Thank you!

If you get an error about time.monotonic(), run it with python3 instead of python.

Could be nice to set up a github repo Smile
#5
finally got around to trying it, and it works really well I must say Smile good job

edit: suggestions on how to best run it at startup ?
You can find me on IRC, Discord and Twitter


#6
You would need to run in in your X session, so most likely a proper file in ~/.config/autostart would do it. But I haven't looked into those details yet.
#7
(08-21-2017, 11:25 AM)daid Wrote: You would need to run in in your X session, so most likely a proper file in ~/.config/autostart would do it. But I haven't looked into those details yet.

Was the first thing I did - didn't work however. Perhaps I did something wrong.
You can find me on IRC, Discord and Twitter


#8
Running it in a terminal for now, look's good! Will be testing it some more! Smile

Thanks!
#9
(08-21-2017, 06:44 AM)Luke Wrote: finally got around to trying it, and it works really well I must say Smile good job

edit: suggestions on how to best run it at startup ?

I made a wrapper shell script that just starts it with
Code:
sudo python3 PATH/touchpadsleep.py
 (my user account has NOPASSWD in sudoers) 

and added that shell script in
System>Preferences>Personal>Startup
#10
(08-25-2017, 10:05 AM)combs Wrote:
(08-21-2017, 06:44 AM)Luke Wrote: finally got around to trying it, and it works really well I must say Smile good job

edit: suggestions on how to best run it at startup ?

I made a wrapper shell script that just starts it with
Code:
sudo python3 PATH/touchpadsleep.py
 (my user account has NOPASSWD in sudoers) 

and added that shell script in
System>Preferences>Personal>Startup

Ah. Yes, I tried that too - but didn't think of setting no password for my account ... Thanks for sharing this, although I still would like to keep my password for a variety or reasons.
You can find me on IRC, Discord and Twitter




Possibly Related Threads…
Thread Author Replies Views Last Post
  How to enable touchpad natural scrolling? plumlis 3 12,612 07-19-2020, 02:46 PM
Last Post: Martin Gruber
  Disable touchpad tap to click? colin.faulkingham 25 56,110 04-27-2020, 07:31 PM
Last Post: ab1jx
Sad touchpad edges scrolling kurai021 11 22,968 07-09-2017, 05:56 PM
Last Post: Luke

Forum Jump:


Users browsing this thread: 1 Guest(s)