So ordnen Sie Tastaturtasten basierend auf der Dauer des Gedrückthaltens einer Taste neu zu

So ordnen Sie Tastaturtasten basierend auf der Dauer des Gedrückthaltens einer Taste neu zu

Ich möchte die Tasten auf meinem Nummernblock so belegen, dass sie sich je nach Dauer des Tastendrucks unterschiedlich verhalten. Hier ein Beispiel:

Wenn ich die Nummernblocktaste 9 für weniger als 300 ms gedrückt halte, wird der Tastenbefehl „Vorheriger Tab“ gesendet Ctrl+Tab

Wenn ich die Nummernblocktaste 9 für 300-599 ms gedrückt halte, wird der Tastenbefehl „Neuer Tab“ gesendet Ctrl+T

Wenn ich die Nummernblocktaste 9 für 600-899 ms gedrückt halte, wird der Tastenbefehl „Tab/Fenster schließen“ gesendet Ctrl+W

Wenn ich die Taste 9 auf dem Ziffernblock länger als 899 ms gedrückt halte, passiert nichts, falls ich das gewünschte Zeitfenster verpasse.

Unter Windows könnte ich dies mit AutoHotKey und unter OS XI mit ControllerMate tun, aber ich kann unter UNIX/Linux kein Tool finden, das eine Neuzuordnung der Tasten basierend auf der Dauer des Drückens einer Taste ermöglicht.

Wenn Sie ein Tool kennen, das mein Problem lösen kann, stellen Sie bitte ein Skript oder Codebeispiel zur Verfügung, das das oben beschriebene Verhalten der bedingten Tastenhaltedauer demonstriert. Es muss nicht der vollständige Code sein, um mein Beispiel zu lösen, aber es sollte ausreichen, damit ich ihn für mein Beispiel umfunktionieren kann.

Antwort1

Ich habe das gerade geschrieben inC:

#include <stdio.h>
#include <curses.h>
#include <time.h> //time(0)
#include <sys/time.h>                // gettimeofday()
#include <stdlib.h>

void waitFor (unsigned int secs) {
    //credit: http://stackoverflow.com/a/3930477/1074998
    unsigned int retTime = time(0) + secs;   // Get finishing time.
    while (time(0) < retTime);               // Loop until it arrives.
}

int
main(void) {

    struct timeval t0, t1, t2, t3;
    double elapsedTime;

    clock_t elapsed_t = 0;
    int c = 0x35;

    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    halfdelay(5); //increae the number if not working //adjust below `if (elapsedTime <= 0.n)` if this changed
    printf("\nSTART again\n");

    elapsed_t = 0;
    gettimeofday(&t0, NULL);

    float diff;

    int first = 1;
    int atleast_one = 0;

      while( getch() == c) { //while repeating same char, else(ffff ffff in my system) break

            int atleast_one = 1;

            if (first == 1) {
                gettimeofday(&t1, NULL);
                first = 0;
            }

            //printf("DEBUG 1 %x!\n", c);
            gettimeofday(&t2, NULL);
            elapsedTime = (t2.tv_sec - t1.tv_sec) + ((t2.tv_usec - t1.tv_usec)/1000000.0); 

            if (elapsedTime > 1) { //hit max time

                printf("Hit Max, quit now. %f\n", elapsedTime);
                system("gnome-terminal");
                //waitFor(4);

                int cdd;
                while ((cdd = getch()) != '\n' && cdd != EOF);
                endwin();

                exit(0);
            }

            if(halfdelay(1) == ERR) { //increae the number if not working
                //printf("DEBUG 2\n");
                //waitFor(4);
                break; 
                }
            else {
                //printf("DEBUG 3\n");
                }
        }

    if (atleast_one == 0) {
            //gettimeofday(&t1, NULL);
            t1 = t0;
    }

    gettimeofday(&t3, NULL);
    elapsedTime = (t3.tv_sec - t1.tv_sec) + ((t3.tv_usec - t1.tv_usec)/1000000.0); 
    printf("Normal quit %f\n", elapsedTime);
    if (elapsedTime > 0.6) { //this number based on halfdelay above
        system("gedit &");
        //system("xdotool key shift+left &");
        //system("mplayer -vo caca -quiet 'video.mp4' &");
        //waitFor(4);
    }
    else if (elapsedTime <= 0.6) {
        system("xdotool key ctrl+shift+t &");
        //waitFor(4);
    }

    int cdd;
    while ( (cdd = getch() ) != '\n' && cdd != EOF);
    endwin();
    return 0; 

}

Verwenden Sie showkey -aFolgendes, um den Bind-Schlüsselcode zu erhalten:

xb@dnxb:/tmp$ sudo showkey -a

Press any keys - Ctrl-D will terminate this program

^[[24~   27 0033 0x1b #pressed F12
         91 0133 0x5b
         50 0062 0x32
         52 0064 0x34
        126 0176 0x7e
5        53 0065 0x35 #pressed Numpad 5, 5 is the keycode used in `bind`
^C        3 0003 0x03
^D        4 0004 0x04
xb@dnxb:/tmp$ 

Geben Sie den Bind-Tastencode 5 und den zugehörigen Befehl (z. B. „run /tmp/.a.out“) in ~/.bashrc ein:

bind '"5":"/tmp/a.out\n"'

Beachten Sie, dass der relevante Schlüsselcode auch im Quellcode geändert werden muss (der Hex-Wert kann sudo showkey -aauch von oben bezogen werden):

int c = 0x35;

Kompilieren mit (Ausgabe /tmp/a.outin meinem Beispiel an):

cc filename.c -lcurses

Demonstration:

Numpad 5, kurz drücken, um neue Registerkarte zu öffnen, mittel drücken, um gedit zu öffnen, und lange drücken, um Gnome-Terminal zu öffnen.

Bildbeschreibung hier eingeben

Dies ist nicht direkt in jedem Fenster des Gnome-Desktop-Managers anwendbar, aber ich denke, es sollte Ihnen eine Vorstellung davon geben, wie (schwierig) es zu implementieren ist. Es funktioniert auch in der virtuellen Konsole (Strg+Alt+N) und in einigen Terminalemulatoren (z. B. Konsole, Gnome-Terminal, Xterm).

P.S.: Ich bin kein AC-Programmierer, also verzeihen Sie mir, wenn dieser Code nicht optimiert ist.

[AKTUALISIEREN]

Die vorherige Antwort funktioniert nur in der Shell und erforderte Fokus, daher denke ich, dass die Analyse von /dev/input/eventX die Lösung ist, damit es in der gesamten X-Sitzung funktioniert.

Ich möchte das Rad nicht neu erfinden. Ich spiele mit evtestdem Dienstprogramm herum und modifizierte den unteren Teil vonevtest.cmit meinem eigenen Code:

int onHold = 0;
struct timeval t0;
double elapsedTime;
int hitMax = 0;

while (1) {
    rd = read(fd, ev, sizeof(struct input_event) * 64);

    if (rd < (int) sizeof(struct input_event)) {
        perror("\nevtest: error reading");
        return 1;
    }

    system("echo 'running' >/tmp/l_is_running 2>/tmp/l_isrunning_E &");
    for (i = 0; i < rd / sizeof(struct input_event); i++) {

        //system("date >/tmp/l_date 2>/tmp/l_dateE &");

        if (ev[i].type == EV_KEY) {
            if ( (ev[i].code == 76) ) {

                if (!onHold) {
                    onHold = 1;
                    t0 = ev[i].time;
                    hitMax = 0;
                }
                if (!hitMax) { //to avoid hitMax still do the time checking instruction, you can remove hitMax checking if you think it's overkill, but still hitMax itself is necessary to avoid every (max) 2 seconds will repeatly system();
                    elapsedTime = (ev[i].time.tv_sec - t0.tv_sec) + ((ev[i].time.tv_usec - t0.tv_usec)/1000000.0);
                    printf("elapsedTime: %f\n", elapsedTime);
                    if (elapsedTime > 2) {
                        hitMax = 1;
                        printf("perform max time action\n");
                        system("su - xiaobai -c 'export DISPLAY=:0; gedit &'");
                    }
                }

                if (ev[i].value == 0)  {
                    printf("reseted ...... %d\n", ev[i].value);
                    onHold = 0;
                    if (!hitMax) {
                        if (elapsedTime > 1) { //just ensure lower than max 2 seconds
                            system("su - xiaobai -c 'export DISPLAY=:0; gnome-terminal &'");
                        } else if (elapsedTime > 0.5) { 
                            system("su - xiaobai -c \"export DISPLAY=:0; vlc '/home/xiaobai/Downloads/videos/test/Pokémon Red_Blue_Yellow Gym Leader Battle Theme Remix-CbJTkx7QUJU.mp4' &\"");
                        } else if  (elapsedTime > 0.2) {
                            system("su - xiaobai -c 'export DISPLAY=:0; nautilus &'");
                        }
                    } else { //else's max system() already perform
                        hitMax = 0;
                    }
                }
            }
        }
    }
}

Beachten Sie, dass Sie den Benutzernamen (Abonnierenist mein Benutzername). Und das if ( (ev[i].code == 76) ) {ist auch mein Numpad 5-Tastencode. Möglicherweise müssen Sie den ev[i].code manuell ausdrucken, um dies zu bestätigen. Und natürlich sollten Sie auch den Videopfad ändern :)

Kompilieren und testen Sie es direkt mit (der ``-Teil dient dazu, das richtige zu erhalten /dev/input/eventN):

$ gcc /home/put_your_path/my_long_press.c -o /home/put_your_path/my_long_press; sudo /home/put_your_path/my_long_press `ls -la /dev/input/by-path/* | grep kbd |  echo "/dev/input/""$(awk -F'/' '{print $NF}')" ` &

Beachten Sie, dass /by-id/dies unter Fedora 24 nicht funktioniert, daher ändere ich es in /by-path/. Unter Kali gibt es dieses Problem nicht.

Mein Desktop-Manager ist gdm3:

$ cat /etc/X11/default-display-manager 
/usr/sbin/gdm3

Also habe ich diese Zeile eingegeben, /etc/gdm3/PostLogin/Defaultum diesen Befehl beim GDM-Start als Root auszuführen ( /etc/X11/Xsession.d/*funktioniert nicht):

/home/put_your_path/my_long_press `ls -la /dev/input/by-id/* | grep kbd |  echo "/dev/input/""$(awk -F'/' '{print $NF}')" 2>/tmp/l_gdm` 2>/tmp/l_gdmE &

Aus unbekanntem Grund etc/gdm/PostLogin/Defaultfunktioniert es nicht unter Fedora 24' gdm, was mir "Zugriff verweigert" beim Überprüfen /tmp/l_gdmEdes Protokolls. Manuelle Ausführung jedoch kein Problem.

Demonstration:

Nummernblock 5, kurzes Drücken (<=0,2 Sekunden) wird ignoriert, kurzes Drücken (0,2 bis 0,5 Sekunden) öffnet nautilus, mittleres Drücken (0,5 bis 1 Sekunde) öffnet vlczum Abspielen eines Videos, langes Drücken (1 bis 2 Sekunden) öffnet gnome-terminalund Timeout-Drücken (2 Sekunden) öffnet gedit.

Bildbeschreibung hier eingeben

Ich habe den vollständigen Code (nur eine Datei) hier hochgeladen.

[nochmals UPDATE]

[1] Mehrere Schlüsselflüsse hinzugefügt und notify-sendFehler durch Definieren behoben DBUS_SESSION_BUS_ADDRESS. [2] Hinzugefügt XDG_CURRENT_DESKTOPund GNOME_DESKTOP_SESSION_IDum sicherzustellen, dass die Konsole die GUI des Gnome-Designs verwendet (Ändern Sie es, wenn Sie Gnome nicht verwenden).

Ich habe meinen Code hier aktualisiert.

Beachten Sie, dass dieser Code keinen Tastenkombinationsfluss verarbeitet, z. B. Ctrl+ t.

AKTUALISIEREN:

Es gibt mehrere Geräteschnittstellen, bei denen die Reihenfolge der Einträge /dev/input/by-path/XXX-eventN zufällig ist. Daher ändere ich den Befehl wie /etc/gdm3/PostLogin/Defaultfolgt ( Chesenist mein Tastaturname, in Ihrem Fall sollten Sie ihn grep Razerstattdessen ändern):

/your_path/my_long_press "$(cat /proc/bus/input/devices | grep -i Chesen -A 4 | grep -P '^(?=.*sysrq)(?=.*leds)' |  tr ' ' '\n' | ls /dev/input/`grep event`)" 2>/tmp/l_gdmE &

Sie können den eventN-Auszug aus folgendem Dokument ausprobieren cat /proc/bus/input/devices | grep -i Razer -A 4:

$ cat /proc/bus/input/devices | grep -i Razer -A 4
N: Name="Razer Razer Naga Chroma"
P: Phys=usb-0000:00:14.0-1.3/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.3/3-1.3:1.0/0003:1532:0053.0003/input/input6
U: Uniq=
H: Handlers=mouse2 event5 
--
N: Name="Razer Razer Naga Chroma"
P: Phys=usb-0000:00:14.0-1.3/input1
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.3/3-1.3:1.1/0003:1532:0053.0004/input/input7
U: Uniq=
H: Handlers=sysrq kbd event6 
--
N: Name="Razer Razer Naga Chroma"
P: Phys=usb-0000:00:14.0-1.3/input2
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1.3/3-1.3:1.2/0003:1532:0053.0005/input/input8
U: Uniq=
H: Handlers=sysrq kbd leds event7 
$ 

Im obigen Beispiel sudo cat /dev/input/event7wird nur dann eine seltsame Ausgabe gedruckt, wenn Sie auf die 12 Ziffern der Razer-Maus klicken, die das oben zu verwendende Muster „sysrq kbd leds event7“ hat grep -P '^(?=.*sysrq)(?=.*leds)'(Ihr Muster kann abweichen). sudo cat /dev/input/event6Eine seltsame Ausgabe wird nur gedruckt, wenn Sie auf die mittlere Auf-/Ab-Taste klicken. Eine sudo cat /dev/input/event5seltsame Ausgabe wird gedruckt, wenn Sie Ihre Maus bewegen und das Rad scrollen.

[Update: Unterstützt das erneute Einstecken des Tastaturkabels zum Neuladen des Programms]

Folgendes sollte selbsterklärend sein:

$ lsusb #to know my keyboard is idVendor 0a81 and idProduct 0101
...
Bus 001 Device 003: ID 0a81:0101 Chesen Electronics Corp. Keyboard

$ cat /etc/udev/rules.d/52-hole-keyboard.rules #add this line with your idVendor and idProduct above in custom udev rules file
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0a81", ATTR{idProduct}=="0101", MODE="0666", GROUP="plugdev", RUN+="/bin/bash -c 'echo 1 > /tmp/chesen_plugged'"

$ cat /usr/local/bin/inotifyChesenPlugged #A long run listener script to listen for modification of /tmp/chesen_plugged #Ensures `inotifywait` has been installed first.
touch /tmp/chesen_plugged
while inotifywait -q -e modify /tmp/chesen_plugged >/dev/null; do
        killall -9 my_long_press
        /usr/local/bin/startLongPress &
done

$ cat /usr/local/bin/startLongPress #the executable script run the long press executable #Change with your pattern as explained above.
#!/bin/bash
<YOUR_DIR>/my_long_press "$(cat /proc/bus/input/devices | grep -i Chesen -A 4 | grep -P '^(?=.*sysrq)(?=.*leds)' |  tr ' ' '\n' | ls /dev/input/`grep event`)" 2>/tmp/l_gdmE) & disown

$ cat /etc/gdm3/PostLogin/Default #the executable startup script run listener and long press script
/usr/local/bin/inotifyChesenPlugged &
/usr/local/bin/startLongPress &

Antwort2

Sie finden möglicherweise ein Tool, das mit einer bestimmten Gruppe von Programmen funktioniert, es wird jedoch kein global verwendbares Tool geben, da das zeitbezogene Verhalten in Anwendungen in X und nicht im Fenstersystem erfolgt.

Antwort3

hast du die Xmodmap überprüft?

xmodmap ist ein Dienstprogramm zum Ändern von Keymaps und Zeigertastenzuordnungen in Xorg

https://wiki.archlinux.org/index.php/Xmodmap

verwandte Informationen