Acabo de escribir esto 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;
}
Use showkey -a
para obtener el código clave de enlace:
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$
Ponga el código clave de enlace 5 y su comando (por ejemplo, ejecutar /tmp/.a.out
) en ~ / .bashrc:
bind '"5":"/tmp/a.out\n"'
Tenga en cuenta que el código clave relevante también debe cambiar en el código fuente (el valor hexadecimal también puede obtenerse desde sudo showkey -a
arriba):
int c = 0x35;
Compilar con (salida a /tmp/a.out
en mi ejemplo):
cc filename.c -lcurses
Demostración:
Teclado numérico 5, presione brevemente para abrir una nueva pestaña, presione medianamente para abrir gedit y presione prolongadamente para abrir gnome-terminal.
Esto no es directamente aplicable en ninguna ventana en el administrador de escritorio gnome, pero creo que debería darle una idea de cómo (difícil) implementarlo. También funciona en la Consola virtual (Ctrl + Alt + N), y funciona en algún emulador de terminal (por ejemplo, konsole, gnome-terminal, xterm).
p / s: no soy un programador de CA, así que perdóname si este código no está optimizado.
[ACTUALIZAR]
La respuesta anterior solo funciona en shell y requiere el enfoque, por lo que creo que analizar / dev / input / eventX es la solución para trabajar en toda la sesión X.
No quiero reinventar la rueda. Juego con la evtest
utilidad y modifiqué la parte inferior de evtest.c con mi propio código:
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;
}
}
}
}
}
}
Tenga en cuenta que debe cambiar la parte del nombre de usuario ( xiaobai es mi nombre de usuario). Y también if ( (ev[i].code == 76) ) {
es mi código clave Numpad 5, es posible que deba imprimir manualmente el código ev [i]. Para confirmar dos veces. Y, por supuesto, también debes cambiar la ruta del video :)
Compílelo y pruébelo directamente con (la parte `` es para obtener el correcto /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}')" ` &
Tenga en cuenta que /by-id/
no funciona en Fedora 24, así que lo cambio a / by-path /. Kali no tiene tal problema.
Mi administrador de escritorio es gdm3:
$ cat /etc/X11/default-display-manager
/usr/sbin/gdm3
Entonces, puse esta línea /etc/gdm3/PostLogin/Default
para ejecutar este comando como root en el inicio de gdm ( /etc/X11/Xsession.d/*
no funciona):
/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 &
Por una razón desconocida / etc/gdm/PostLogin/Default
no funciona en Fedora 24 'gdm que me da " Permiso denegado " cuando verifica el /tmp/l_gdmE
registro. Sin embargo, no se ejecutan manualmente.
Demostración:
Teclado numérico 5, se ignorará la presión instantánea (<= 0.2 segundos), presión corta (0.2 a 0.5 segundos) abierta nautilus
, presión media (0.5 a 1 segundo) abierta vlc
para reproducir video, presión larga (1 a 2 segundos) abierto gnome-terminal
, y tiempo de espera-presione (2 segundos) abierto gedit
.
Subí el código completo (solo un archivo) aquí .
[ACTUALIZAR de nuevo]
[1] Se agregó flujo de claves múltiples y se corrigió el notify-send
error por definición DBUS_SESSION_BUS_ADDRESS
. [2] Agregado XDG_CURRENT_DESKTOP
y GNOME_DESKTOP_SESSION_ID
para garantizar que konsole use la interfaz de usuario de tema gnome (cámbielo si no está usando gnome).
Actualicé mi código aquí .
Tenga en cuenta que este código no maneja el flujo de teclas de combinación, por ejemplo, Ctrl+ t.
ACTUALIZAR:
Hay múltiples interfaces de dispositivo cuya secuencia de entradas / dev / input / by-path / XXX-eventN es aleatoria. Así que cambio el comando de la /etc/gdm3/PostLogin/Default
siguiente manera ( Chesen
es el nombre de mi teclado, para su caso, debería cambiarlo a grep Razer
):
/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 &
Puedes probar el extracto de 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
$
En este ejemplo anterior, solo sudo cat /dev/input/event7
imprimirá resultados extraños cuando haga clic en los 12 dígitos del mouse Razer, que tiene el patrón "sysrq kbd leds event7" para usar grep -P '^(?=.*sysrq)(?=.*leds)'
arriba (su patrón puede variar). sudo cat /dev/input/event6
imprimirá resultados extraños solo cuando haga clic en la tecla central arriba / abajo. Mientras sudo cat /dev/input/event5
imprime resultados extraños cuando mueve el mouse y desplaza la rueda.
[Actualización: admite el cable del teclado Replug para volver a cargar el programa]
Lo siguiente debe explicarse por sí mismo:
$ 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 &