Cara memetakan ulang kunci di Linux hanya untuk keyboard tertentu

18

Saya baru-baru ini membeli keyboard Unicomp yang datang dengan alt kanan dan tombol Windows yang ditukar. Keyboard mengidentifikasi seperti ini di lsusb:

Bus 003 Device 002: ID 17f6:0822 Unicomp, Inc 

Apakah ada cara untuk membuat kernel (yaitu bukan berbasis xmodmap) menukar tombol alt kanan dan windows sehingga setiap aplikasi melihatnya di tempat yang ditukar bahkan jika mereka mendapatkan input keyboard mentah (menukar barang dengan xmodmap tidak akan melakukan itu) ? Apakah ada cara untuk memilikinya hanya untuk keyboard yang satu ini?

FUZxxl
sumber
Saya menduga Anda bisa melakukan ini dengan udev dengan mencocokkan nomor seri keyboard dan kemudian memanggil skrip yang melakukan remapping. Anda mungkin perlu skrip serupa untuk dipanggil pada detach agar perangkat dapat mengembalikannya.
selai
1
@ jo. Apakah ini akan memetakan kembali semua keyboard yang terpasang? Saya tidak dapat membayangkan bahwa Linux sangat tidak fleksibel sehingga hanya dapat mengatur satu tabel pemetaan untuk semua keyboard (USB) yang terpasang.
FUZxxl
@ jam Selain itu, Anda akan sangat membantu saya jika Anda bisa menjelaskan cara melakukan swapping yang sebenarnya. Saya tidak berhasil menemukan sesuatu yang berguna dalam hal ini, hanya hal-hal xmodmap (yang tidak ingin saya gunakan).
FUZxxl
Jika Anda tidak ingin menggunakan xmodmap, apa yang Anda minta tampaknya terlalu spesifik untuk pengetahuan saya untuk membantu Anda menyesal. Metode yang saya usulkan akan menggunakan xmodmap untuk menukar kode kunci dengan kunci-kunci itu untuk semua perangkat, selama durasi keyboard spesifik Anda terpasang, dan kemudian memasangnya kembali. Apakah Anda berharap dapat menggunakan beberapa keyboard secara bersamaan?
selai
@ jam Jika saya menggunakan Xmodmap, program X masih akan melihat kode kunci yang salah karena server X juga mengirimkan kode kunci yang tidak diterjemahkan ke klien. Ini penting misalnya untuk video game. Seharusnya ada solusi di kernel yang tidak membuat hidup saya lebih rumit dengan aplikasi yang membaca kode pindai.
FUZxxl

Jawaban:

27

Ya, dimungkinkan menggunakan XKB. Tidak seperti xmodmap, XKB dapat memetakan ulang kunci Anda untuk masing-masing perangkat.

Catatan: Pastikan Anda memiliki xkbcomp> 1.2.0

Pertama-tama daftarkan perangkat Anda dengan:

xinput list

Anda akan mendapatkan sesuatu seperti ini:

⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Pen stylus               id=11   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Finger touch             id=12   [slave  pointer  (2)]
⎜   ↳ Logitech USB-PS/2 Optical Mouse           id=13   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Pen eraser               id=14   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Finger pad               id=15   [slave  pointer  (2)]
⎜   ↳ GASIA USB KB V11                          id=17   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Power Button                              id=7    [slave  keyboard (3)]
    ↳ G19 Gaming Keyboard                       id=8    [slave  keyboard (3)]
    ↳ G19 Gaming Keyboard                       id=9    [slave  keyboard (3)]
    ↳ Logitech G19 Gaming Keyboard              id=10   [slave  keyboard (3)]
    ↳ GASIA USB KB V11                          id=16   [slave  keyboard (3)]

Identifikasi string perangkat Anda dan edit skrip shell berikut, ubah baris sed dengan yang sesuai dengan nama perangkat Anda. Kemudian ganti kunci yang perlu Anda buat ulang.

Contoh: Muat xevdan tekan tombol yang ingin Anda remap. Misalkan Anda mengetahui kode kunci 84. Cari 84 di https://gist.github.com/zoqaeski/3880640 . Nama kuncinya ada <KP5>. Kemudian cari kunci yang Anda inginkan digantikan oleh (dalam tautan yang sama, lebih jauh di bawah ) dan salin apa yang ada di dalam tanda kurung. Ulangi proses ini untuk semua tombol yang Anda inginkan.

remote_id=$(
    xinput list |
    sed -n 's/.*GASIA.*id=\([0-9]*\).*keyboard.*/\1/p'
)
[ "$remote_id" ] || exit

# remap the following keys, only for my custom vintage atari joystick connected
# through an old USB keyboard:
#
# keypad 5 -> keypad 6
# . -> keypad 2
# [ -> keypad 8
# left shift -> left control

mkdir -p /tmp/xkb/symbols
# This is a name for the file, it could be anything you
# want. For us, we'll name it "custom". This is important
# later.
#
# The KP_* come from /usr/include/X11/keysymdef.h
# Also note the name, "remote" is there in the stanza
# definition.
cat >/tmp/xkb/symbols/custom <<\EOF

xkb_symbols "remote" {
    key <KP5>  { [ KP_Right, KP_6, U2192, U21D2 ]       };
    key <I129> { [ KP_Down, KP_2, U2193, U21D3 ]       };
    key <AD12> { [ KP_Up, KP_8, U2191, U21D1 ]  };
    key <LFSH> { [ Control_L ]        };
};
EOF

# (1) We list our current definition
# (2) Modify it to have a keyboard mapping using the name
#     we used above, in this case it's the "remote" definition
#     described in the file named "custom" which we specify in
#     this world as "custom(remote)".
# (3) Now we take that as input back into our definition of the
#     keyboard. This includes the file we just made, read in last,
#     so as to override any prior definitions.  Importantly we 
#     need to include the directory of the place we placed the file
#     to be considered when reading things in.
#
# Also notice that we aren't including exactly the 
# directory we specified above. In this case, it will be looking
# for a directory structure similar to /usr/share/X11/xkb
# 
# What we provided was a "symbols" file. That's why above we put
# the file into a "symbols" directory, which is not being included
# below.
setxkbmap -device $remote_id -print \
 | sed 's/\(xkb_symbols.*\)"/\1+custom(remote)"/' \
 | xkbcomp -I/tmp/xkb -i $remote_id -synch - $DISPLAY 2>/dev/null

Kemudian sumber itu (Anda dapat menambahkannya ke .xinitrc Anda). Semua selesai! Sekarang, menekan tombol akan menghasilkan output yang diinginkan, hanya untuk perangkat yang Anda tentukan.

Sunting : Baru-baru ini, saya perhatikan bahwa, karena suatu alasan, konfigurasi baru tidak segera diterapkan. Pertama-tama Anda harus menekan tombol pada keyboard Anda yang lain , kemudian menguji kunci yang dikonfigurasi pada keyboard Anda yang dimodifikasi. Saya tidak tahu mengapa ini terjadi, mungkin semacam cache.

Watcom
sumber
Biarkan saya mencoba ini pada hari Senin ketika saya kembali ke komputer tempat saya menggunakan keyboard ini.
FUZxxl
1
a) sed -n 's/.*G19 Gaming Keyboard.*id=\([0-9]*\).*keyboard.*/\1/p' c) Ya, Anda harus mengujinya terlebih dahulu untuk mengganti $remote_iddengan nomor id. Perhatikan ada dua referensi ke $remote_idsana, apakah Anda mengubah keduanya?
Watcom
1
Oh, dan saat menguji hard-coded $remote_id, pastikan Anda mengomentari baris [ "$remote_id" ] || exitjika Anda belum melakukannya, maka itu hanya akan menyelamatkan.
Watcom
1
@ stats-hb $9tidak akan berfungsi, maksudmu 9?
Watcom
1
ini berfungsi untuk saya lampjs.wordpress.com/2015/06/26/…
usil
6

Untuk siapa pun yang datang ke sini dari Google dan menginginkan jawaban yang lebih sesuai dengan apa yang awalnya ditanyakan oleh si penanya, saya mengetahui dua cara untuk memetakan ulang peristiwa di evdevtingkat sehingga perubahan tersebut berlaku untuk semua aplikasi:

  1. udev menyediakan API untuk memodifikasi entri basis data perangkat keras yang mengontrol pemetaan antara kode dan kode kunci. Halaman ArchiWiki ini , yang berisi instruksi, secara eksplisit mengatakan bahwa itu akan berfungsi untuk input X11 dan konsol.

    Intinya adalah Anda membuat entri khusus /etc/udev/hwdb.d/yang terdiri dari pola kecocokan perangkat dan beberapa definisi remapping scancode-to-keycode, kemudian jalankan systemd-hwdb updateuntuk membangun kembali database dan udevadm triggermenerapkannya tanpa reboot.

  2. Mengingat bahwa Wayland tidak menggunakan subsistem keyboard X11 dan kompositor Wayland utama seperti GNOME Shell dan Weston tidak menerapkan UI untuk mengonfigurasi aspek-aspek yang relevan dari libinput, seseorang menulis daemon bernama evdevremapkeys yang menyelesaikan masalah dengan cara yang sama dengan driver ruang pengguna G15Daemon untuk Logitech G15 keyboard gaming.

    (Ini menelan peristiwa yang ingin dipetakan kembali, jadi tidak ada yang mendengarkannya di perangkat yang dapat melihatnya, lalu memancarkan peristiwa yang diperbaiki melalui uinputAPI untuk membuat perangkat input tingkat kernel dari userspace.)

ssokolow
sumber
Saya datang ke sini dari DuckDuckGo, tetapi terima kasih atas jawabannya (:
sm4rk0
0

Bagi mereka yang tidak berhasil dengan opsi @Watcom, cukup masukkan file pemetaan baru Anda, seperti:

xkb_symbols "remote" {
    key <KP5>  { [ KP_Right, KP_6, U2192, U21D2 ]       };
    key <I129> { [ KP_Down, KP_2, U2193, U21D3 ]       };
    key <AD12> { [ KP_Up, KP_8, U2191, U21D1 ]  };
    key <LFSH> { [ Control_L ]        };
};

ke / usr / share / X11 / xkb / simbol / karena mungkin root (ubuntu, mungkin berbeda untuk distrib Anda), panggil file 'custom'. Minta string tata letak Anda saat ini dengan setxkbmap -device <device id> -print | grep xkb_symbolsdan tambahkan +custompadanya. Atur tata letak baru dengan kunci yang dipetakan dengan dan string tata letak yang dimodifikasi:

setxkbmap -device <device id> -layout "us+ru:2+us:3+inet(evdev)+capslock(grouplock)+custom"

Efek tidak permanen dan sayangnya me-reset ketika keyboard lain terhubung, belum memikirkan cara memperbaikinya. Anda dapat menambahkan perintah di atas untuk Anda .bashrc, jadi kunci ditukar saat restart jika perlu.

Eviltnan
sumber