Tôi chỉ viết điều này trong 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;
}
Sử dụng showkey -a
để lấy mã khóa liên kết:
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$
Đặt mã khóa liên kết 5 và lệnh của nó (ví dụ: chạy /tmp/.a.out
) trong ~ / .bashrc:
bind '"5":"/tmp/a.out\n"'
Lưu ý rằng mã khóa có liên quan cũng cần thay đổi trong mã nguồn (giá trị hex cũng có thể nhận được từ sudo showkey -a
phía trên):
int c = 0x35;
Biên dịch với (đầu ra /tmp/a.out
trong ví dụ của tôi):
cc filename.c -lcurses
Trình diễn:
Numpad 5, nhấn nhanh mở tab mới, nhấn gedit vừa và nhấn gnome-terminal dài.
Điều này không thể áp dụng trực tiếp trong bất kỳ cửa sổ nào trên trình quản lý máy tính để bàn gnome, nhưng tôi nghĩ nó sẽ cung cấp cho bạn một số ý tưởng về cách (khó) để thực hiện nó. Nó cũng hoạt động trong Bảng điều khiển ảo (Ctrl + Alt + N) và hoạt động trong một số trình giả lập thiết bị đầu cuối (ví dụ: konsole, gnome-terminal, xterm).
p / s: Tôi không phải là lập trình viên ac, vì vậy hãy tha thứ cho tôi nếu mã này không được tối ưu hóa.
[CẬP NHẬT]
Câu trả lời trước chỉ hoạt động trong shell và yêu cầu tập trung, vì vậy tôi nghĩ phân tích / dev / input / eventX là giải pháp để hoạt động trong toàn bộ phiên X.
Tôi không muốn phát minh lại bánh xe. Tôi chơi xung quanh với evtest
tiện ích và sửa đổi phần dưới cùng của evtest.c bằng mã của riêng tôi:
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;
}
}
}
}
}
}
Lưu ý rằng bạn nên thay đổi tên người dùng ( xiaobai là tên người dùng của tôi). Và đây cũng if ( (ev[i].code == 76) ) {
là mã khóa Numpad 5 của tôi, bạn có thể cần in thủ công mã ev [i]. Để xác nhận gấp đôi. Và tất nhiên bạn cũng nên thay đổi đường dẫn video :)
Biên dịch và kiểm tra nó trực tiếp với (phần `` để có được chính xác /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}')" ` &
Lưu ý rằng /by-id/
không hoạt động trong Fedora 24, vì vậy tôi thay đổi nó thành / by-path /. Kali không có vấn đề như vậy.
Trình quản lý máy tính để bàn của tôi là gdm3:
$ cat /etc/X11/default-display-manager
/usr/sbin/gdm3
Vì vậy, tôi đặt dòng này /etc/gdm3/PostLogin/Default
để chạy lệnh này với quyền root khi khởi động gdm ( /etc/X11/Xsession.d/*
không hoạt động):
/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 &
Không rõ lý do / etc/gdm/PostLogin/Default
không hoạt động trên Fedora 24 'gdm, điều này cho tôi " Quyền bị từ chối " khi kiểm tra /tmp/l_gdmE
nhật ký. Chạy thủ công không có vấn đề mặc dù.
Trình diễn:
Numpad 5, bấm nhanh (<= 0,2 giây) sẽ bị bỏ qua, nhấn nhanh (0,2 đến 0,5 giây) mở nautilus
, nhấn trung bình (0,5 đến 1 giây) vlc
để phát video, nhấn lâu (1 đến 2 giây) mở gnome-terminal
và hết thời gian - nhấn (2 giây) mở gedit
.
Tôi đã tải lên mã đầy đủ (chỉ có một tệp) ở đây .
[CẬP NHẬT một lần nữa]
[1] Đã thêm nhiều luồng khóa và cố định notify-send
không thành công bằng cách xác định DBUS_SESSION_BUS_ADDRESS
. [2] Đã thêm XDG_CURRENT_DESKTOP
và GNOME_DESKTOP_SESSION_ID
để đảm bảo konsole sử dụng gui theme gnome (Thay đổi nó nếu bạn không sử dụng gnome).
Tôi đã cập nhật mã của tôi ở đây .
Lưu ý rằng mã này không xử lý luồng kết hợp, ví dụ Ctrl+ t.
CẬP NHẬT:
Có nhiều giao diện thiết bị mà chuỗi mục nhập / dev / input / by-path / XXX-eventN là ngẫu nhiên. Vì vậy, tôi thay đổi lệnh /etc/gdm3/PostLogin/Default
như dưới đây ( Chesen
là tên bàn phím của tôi, đối với trường hợp của bạn, bạn nên thay đổi nó thành grep Razer
thay thế):
/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 &
Bạn có thể thử trích xuất eventN từ 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
$
Trong ví dụ này ở trên, sudo cat /dev/input/event7
sẽ chỉ in đầu ra kỳ quái khi nhấp vào 12 chữ số trên chuột Razer, có mẫu "sysrq kbd leds event7" để sử dụng ở grep -P '^(?=.*sysrq)(?=.*leds)'
trên (mẫu của bạn có thể thay đổi). sudo cat /dev/input/event6
sẽ chỉ in đầu ra kỳ quái khi nhấp vào phím lên / xuống giữa. Trong khi sudo cat /dev/input/event5
sẽ in đầu ra kỳ quái khi di chuyển chuột và cuộn bánh xe.
[Cập nhật: Hỗ trợ Thay thế cáp bàn phím để tải lại chương trình]
Sau đây nên tự giải thích:
$ 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 &