Je viens d'écrire ceci en C :
#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;
}
Utilisez showkey -a
pour obtenir le code clé de liaison:
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$
Placez le code clé de liaison 5 et sa commande (par exemple, exécuter /tmp/.a.out
) dans ~ / .bashrc:
bind '"5":"/tmp/a.out\n"'
Notez que le code clé pertinent doit également être modifié dans le code source (la valeur hexadécimale peut également être obtenue par le sudo showkey -a
haut):
int c = 0x35;
Compiler avec (sortie /tmp/a.out
dans mon exemple):
cc filename.c -lcurses
Manifestation:
Pavé numérique 5, appuyez brièvement sur ouvrir un nouvel onglet, appuyez légèrement sur gedit ouvert et appuyez longuement sur gnome-terminal.
Ce n'est pas directement applicable dans aucune fenêtre du gestionnaire de bureau gnome, mais je pense que cela devrait vous donner une idée de la façon (difficile) de le mettre en œuvre. Il fonctionne également dans la console virtuelle (Ctrl + Alt + N) et fonctionne dans certains émulateurs de terminaux (par exemple konsole, gnome-terminal, xterm).
p / s: je ne suis pas programmeur ac, alors pardonnez-moi si ce code n'est pas optimisé.
[MISE À JOUR]
La réponse précédente ne fonctionne que dans le shell et le focus requis, donc je pense que l'analyse du / dev / input / eventX est la solution pour travailler dans toute la session X.
Je ne veux pas réinventer la roue. Je joue avec l' evtest
utilitaire et j'ai modifié la partie inférieure d' evtest.c avec mon propre 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;
}
}
}
}
}
}
Notez que vous devez changer la partie nom d'utilisateur ( xiaobai est mon nom d'utilisateur). Et aussi if ( (ev[i].code == 76) ) {
est mon code clavier Numpad 5, vous devrez peut-être imprimer manuellement le code ev [i]. Pour confirmer deux fois. Et bien sûr, vous devez également changer le chemin de la vidéo :)
Compilez-le et testez-le directement avec (la partie `` est pour obtenir le bon /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}')" ` &
Notez que /by-id/
cela ne fonctionne pas dans Fedora 24, donc je le change en / by-path /. Kali pas un tel problème.
Mon gestionnaire de bureau est gdm3:
$ cat /etc/X11/default-display-manager
/usr/sbin/gdm3
Donc, j'ai mis cette ligne /etc/gdm3/PostLogin/Default
pour exécuter cette commande en tant que root au démarrage de gdm ( /etc/X11/Xsession.d/*
ne fonctionne pas):
/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 &
Pour une raison inconnue / etc/gdm/PostLogin/Default
ne fonctionne pas sur Fedora 24 'gdm qui me donne " Autorisation refusée " lors de la vérification du /tmp/l_gdmE
journal. Exécuter manuellement aucun problème cependant.
Manifestation:
Pavé numérique 5, appui instantané (<= 0,2 seconde) sera ignoré, appui court (0,2 à 0,5 seconde) ouvert nautilus
, appui moyen (0,5 à 1 seconde) ouvert vlc
pour lire la vidéo, appui long (1 à 2 secondes) ouvert gnome-terminal
et timeout-appuyez sur (2 secondes) pour ouvrir gedit
.
J'ai téléchargé le code complet (un seul fichier) ici .
[MISE À JOUR à nouveau]
[1] Ajout d'un flux de clés multiples et correction d'un notify-send
échec par define DBUS_SESSION_BUS_ADDRESS
. [2] Ajouté XDG_CURRENT_DESKTOP
et GNOME_DESKTOP_SESSION_ID
pour s'assurer que konsole utilise le thème gnome gui (Modifiez-le si vous n'utilisez pas gnome).
J'ai mis à jour mon code ici .
Notez que ce code ne gère pas le flux de clés combinées, par exemple Ctrl+ t.
MISE À JOUR:
Il existe plusieurs interfaces de périphérique dont la séquence d'entrées / dev / input / by-path / XXX-eventN est aléatoire. Je change donc la commande /etc/gdm3/PostLogin/Default
comme ci-dessous ( Chesen
c'est mon nom de clavier, pour votre cas, vous devriez le changer à la grep Razer
place):
/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 &
Vous pouvez essayer l'extrait eventN de 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
$
Dans cet exemple ci-dessus, seule sudo cat /dev/input/event7
l'impression bizarre sera imprimée lorsque vous cliquerez sur les 12 chiffres de la souris Razer, qui a le modèle «sysrq kbd leds event7» à utiliser grep -P '^(?=.*sysrq)(?=.*leds)'
ci-dessus (votre modèle peut varier). sudo cat /dev/input/event6
imprime une sortie bizarre uniquement lorsque vous cliquez sur la touche centrale haut / bas. While sudo cat /dev/input/event5
imprimera une sortie bizarre lorsque vous déplacez votre souris et faites défiler la molette.
[Mise à jour: prise en charge du câble du clavier pour recharger le programme]
Ce qui suit devrait être une explication:
$ 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 &