Saya baru saja menulis ini di 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;
}
Gunakan showkey -a
untuk mendapatkan kode kunci bind:
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$
Masukkan kode kunci bind 5 dan perintahnya (mis. Jalankan /tmp/.a.out
) di ~ / .bashrc:
bind '"5":"/tmp/a.out\n"'
Perhatikan bahwa kode kunci yang relevan perlu diubah dalam kode sumber juga (nilai hex bisa dapatkan dari sudo showkey -a
atas juga):
int c = 0x35;
Kompilasi dengan (output ke /tmp/a.out
dalam contoh saya):
cc filename.c -lcurses
Demonstrasi:
Numpad 5, tekan pendek buka tab baru, tekan menengah buka gedit, dan tekan lama buka terminal gnome.
Ini tidak langsung dapat diterapkan di jendela mana pun di gnome desktop manager, tetapi saya pikir itu harus memberi Anda beberapa ide bagaimana (sulit) untuk mengimplementasikannya. Ia bekerja di Virtual Console (Ctrl + Alt + N) juga, dan bekerja di beberapa terminal emulator (misalnya konsole, gnome-terminal, xterm).
p / s: Saya bukan programmer ac, jadi maafkan saya jika kode ini tidak dioptimalkan.
[MEMPERBARUI]
Jawaban sebelumnya hanya bekerja di shell dan fokus yang diperlukan, jadi saya pikir parse / dev / input / eventX adalah solusi untuk bekerja di seluruh sesi X.
Saya tidak ingin menemukan kembali roda. Saya bermain-main dengan evtest
utilitas dan memodifikasi bagian bawah evtest.c dengan kode saya sendiri:
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;
}
}
}
}
}
}
Perhatikan bahwa Anda harus mengubah nama pengguna ( xiaobai adalah nama pengguna saya). Dan juga if ( (ev[i].code == 76) ) {
kode kunci Numpad 5 saya, Anda mungkin perlu mencetak kode ev [i] secara manual untuk mengonfirmasi ganda. Dan tentu saja Anda harus mengubah jalur video juga :)
Kompilasi dan uji langsung dengan (bagian `` untuk mendapatkan yang benar /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}')" ` &
Catatan yang /by-id/
tidak berfungsi di Fedora 24, jadi saya mengubahnya ke / by-path /. Kali tidak ada masalah seperti itu.
Manajer desktop saya adalah gdm3:
$ cat /etc/X11/default-display-manager
/usr/sbin/gdm3
Jadi, saya meletakkan baris ini /etc/gdm3/PostLogin/Default
untuk menjalankan perintah ini sebagai root pada gdm startup ( /etc/X11/Xsession.d/*
tidak berfungsi):
/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 &
Untuk alasan yang tidak diketahui / etc/gdm/PostLogin/Default
tidak bekerja pada Fedora 24 'gdm yang memberi saya " Izin ditolak " saat memeriksa /tmp/l_gdmE
log. Secara manual menjalankan tidak ada masalah.
Demonstrasi:
Numpad 5, tekan cepat (<= 0,2 detik) akan diabaikan, tekan pendek (0,2 hingga 0,5 detik) terbuka nautilus
, tekan sedang (0,5 hingga 1 detik) terbuka vlc
untuk memutar video, tekan lama (1 hingga 2 detik) terbuka gnome-terminal
, dan batas waktu-tekan (2 detik) terbuka gedit
.
Saya mengunggah kode lengkap (hanya satu file) di sini .
[PERBARUI lagi]
[1] Menambahkan aliran banyak kunci dan diperbaiki notify-send
gagal oleh define DBUS_SESSION_BUS_ADDRESS
. [2] Ditambahkan XDG_CURRENT_DESKTOP
dan GNOME_DESKTOP_SESSION_ID
untuk memastikan konsole menggunakan gnome theme gui (Ubah jika Anda tidak menggunakan gnome).
Saya memperbarui kode saya di sini .
Perhatikan bahwa kode ini tidak menangani aliran kunci kombinasi, misalnya Ctrl+ t.
MEMPERBARUI:
Ada beberapa antarmuka perangkat yang urutan entri / dev / input / by-path / XXX-eventN adalah acak. Jadi saya mengubah perintah /etc/gdm3/PostLogin/Default
seperti di bawah ini ( Chesen
adalah nama keyboard saya, untuk kasus Anda, Anda harus mengubahnya menjadi grep Razer
sebagai gantinya):
/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 &
Anda dapat mencoba ekstrak eventN dari 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
$
Dalam contoh di atas, hanya sudo cat /dev/input/event7
akan mencetak output aneh ketika mengklik 12 digit pada mouse Razer, yang memiliki pola "sysrq kbd leds event7" untuk digunakan di grep -P '^(?=.*sysrq)(?=.*leds)'
atas (pola Anda mungkin berbeda). sudo cat /dev/input/event6
akan mencetak output aneh hanya ketika mengklik tombol tengah atas / bawah. Sementara sudo cat /dev/input/event5
akan mencetak output aneh ketika menggerakkan mouse Anda dan menggulirkan roda.
[Pembaruan: Mendukung kabel keyboard Replug untuk memuat ulang program]
Berikut ini harus penjelasan sendiri:
$ 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 &