vaclavhanzl / hacktrack

Move windows by four fingers on trackpad, resize by five, and more...
MIT License
4 stars 0 forks source link
linux python touchpad trackpad window-management xfce4

hacktrack: Move windows by four fingers on trackpad, resize by five, and more...

Being spoiled by window management on both Linux and Mac, I want all the good things combined. Three-finger swipe to change desktop? Great. Alt+mouse anywhere to move/resize window? Much better than aiming at tiny GUI parts but do I really have to reach for both the keyboard and mouse? Four fingers on trackpad should move windows, right? After all, mouse feels evil being spoiled by Mac trackpad. So after a vain search for a system I could configure to respond really well, I wrote this little goody. And I absolutely love my window management now.

Prerequisities

Features

Instalation

You need python3 with libraries evdev and python-libxdo. You also need to be in the input group. And you need to make sure hacktrack is run when you log in to your GUI. Here are the commands for Debian:

sudo apt-get install python3.12-venv python3-dev xdotool git
sudo gpasswd -a YOUR-OWN-USERNAME input

Log out and log back in.

git clone git@github.com:vaclavhanzl/hacktrack.git
cd hacktrack
python3 -m venv env
env/bin/pip3 install python-libxdo evdev

Verify that everything works:

env/bin/python3 hacktrack

Than make sure start-hacktrack is run when you log in to your GUI. For example, with Xfce4, you may do it here: Applications/Settings/Settings Manager, System, Session and Startup. Use full path to the script, something like /home/......./hacktrack/start-hacktrack.

For desktop changes, you will likely need to modify commands used in the hacktrack source according to your desktop setup.

Troubleshooting

You can alternatively clone the code using the https variant:

git clone https://github.com/vaclavhanzl/hacktrack.git

To verify that you are in the input group, do:

groups

and you should have a list containing this group, e.g.:

hanzl cdrom floppy sudo audio dip video plugdev netdev bluetooth lpadmin scanner input
                                                                                 ^^^^^

If input is not there, use the gpasswd command mentioned above and log out and log in.

To test hacktrack, go to the cloned directory and try to run it directly from the command line:

cd hacktrack
env/bin/python3 hacktrack

Look for any errors you get. If you see any import problems, verify installation of libraries by running:

env/bin/python3

and at the python command prompt, try:

import evdev
from xdo import Xdo

Both should work without any error messages. If there are some complaints, make sure you did BOTH the apt-get part of installation AND the pip3 install one. The Xdo python library needs the apt package xdotool.

If you see something like:

PermissionError: [Errno 13] Permission denied: '/dev/input/by-id/usb-Apple_Inc._Magic_Trackpad_2_CC28192005HJ2Y1AM-if01-event-mouse'

you likely need the input group permissions - see above and do not forget to log out and in.

TODO

This is an alpha stage project. Some more automatic installation is certainly due.

Comparison to other projects

I tried whatever I found before writing the tool myself, of course. Rather surprisingly, the key decision which allowed me to make this code simple and ergonomic was to NOT use library like libinput which is there to help me. Instead, I get raw trackpad events directly from the kernel. Sounds scary but is actually very easy. The problem with the (great) libinput is that it does only the things it can do well. It is not a place for experiments. If you want to be on the edge with crazy ideas, you need your experimental code PLUS a hacked version of libinput. This forked hacked libinput gets quickly unmaintained and it clashes with the libinput in your system. On the other hand, working in parallel with libinput (and anything like libinput-gestures on top of it) is really hassle free.

Four fingers move

Four fingers can move in many ways. The tool just computes "center of gravity" (average position) of all four fingers and as this average point moves, the window moves. Use your creativity to find out how to use it with your hands. For example:

Five fingers resize

Just spread/shrink 5 fingers touching the trackpad and you will certainly figure it out. But for the curious, the algorithm looks for a bounding rectangle which contains your touch points. Relative changes of this rectangle's width and height then change width and height of the window. Again, you can get creative in many ways:

All this is actually fun to experiment with, you will certainly find a way you like.

Three fingers desktop change

This one is actually just boring port of functionality I like on Mac. You can also get it easily with libinput-gestures so you may want to just disable it in hacktrack by changing this:

@event_eater
def three_finger_desktop_drag():

into this (comment out the decorator):

#@event_eater
def three_finger_desktop_drag():

If you want to use it, you need to match your desktop layout and the source code. It is no rocket science. My desktop is Xfce4 and I have a row of virtual desktops in a panel which appears when mouse pointer is at the lower edge of my display. When the pointer is elsewhere, the panel autohides. This part of the hacktrack source code forms the interface to my desktops:

def desk_show():
    os.system("xfconf-query -c xfce4-panel -p /panels/panel-2/autohide-behavior -s 0")
def desk_hide(): # still shown if mouse at lower screen edge
    os.system("xfconf-query -c xfce4-panel -p /panels/panel-2/autohide-behavior -s 2")
def desk_left(): # like swipe-left on Mac (windows move left, our view moves right)
    os.system("xdotool key alt+ctrl+Right")
def desk_right():
    os.system("xdotool key alt+ctrl+Left")

Also, you may use other commands than xfconf-query and xdotool to send instructions to your desktop.

Absolute pointer positioning by tap

This one is really experimental and is disabled in the code:

#@event_eater
def abs_pos_mouse_by_tap():

Remove the # to activate it. Also, unless your monitor happens to be 4K as the mine is, put the right size here:

desktop_range = ((0, 3840), (0, 2160)) # x, y

Then you can tap the trackpad (slightly less than what would make it to click) at any point and the mouse cursor will appear at the corresponding absolute position of your screen. It is a neat way to find your cursor (or in fact not to search for it but place it where you want it) but I did not like it as much as the other features.

Your own crazy idea

This is why you came here, right? It is really easy. The @event_eater decorator puts your procedure among those who recieve slightly cooked trackpad events (if you ever worked with mouse moving events, this is a similar thing). Try this:

@event_eater
def eater():
    while True:
        x = (yield)
        print(x)

and look what is printed and than do something useful instead of the print. The code is full of examples of all the idioms you might need. Enjoy!

Warning

Your window environment may contain elements which technically could be moved/resized by hacktrack but you do not want it. Code tries to avoid moving these:

   if str(name).startswith("b'Desktop'"):
       # we are technically able to move this but do not want to
       print("Avoided Desktop drag")
       continue

and it works good enough for me but can be different for you.

More Troubleshooting

For a lot more of similar wisdom, you may have look at libinput-gestures or even install it. It has similar dependencies so if you make it to work for you, quite likely your computer will be also ready for hacktrack by then.

Discussions and Contact

You can discuss hacktrack in public here in Discussions. If you want to tell me more personally that you love this or hate this, message @vaclavh@sigmoid.social on Mastodon.