Объяснение `истории -c; `в следующем хорошо известном фрагменте для сохранения истории bash

После некоторого времени и чтения doc / code я наконец нашел решение.

Если вы просто хотите протестировать скрипт (в конце этого ответа ), просто запустите его от имени пользователя root с:

$ chmod +x completely_fake_tablet.py
$ sudo pip3 install libevdev
$ sudo./completely_fake_tablet.py

, затем откройте gimp, добавьте устройство в качестве устройства ввода, выберите кисть, например Pencil Generic, и наслаждайтесь. Если вы хотите получить более подробную информацию, прочитайте следующее:

Подводя итог, система очень придирчива, и вы хотите убедиться,:

  • Вы включаете libevdev.INPUT_PROP_DIRECT, чтобы сказать, что у вас есть планшет -как устройство (см. ссылку на документ выше)
  • Вы включаете все планшеты -, например такие инструменты, как:

    • libevdev.EV_KEY.BTN_TOOL_PENбудет использоваться, чтобы сказать, когда перо находится близко к планшету или нет, libevdev.EV_KEY.BTN_TOUCHчтобы сказать, когда вы нажимаете
    • libevdev.EV_KEY.BTN_STYLUS/ libevdev.EV_KEY.BTN_STYLUS2, что соответствует кнопке на стилусе
    • libevdev.EV_ABS.ABS_{X,Y}для позиции (обязательно укажите минимальное значение, максимальное значение, и разрешение:без разрешения, устройство никогда не будет обнаружено!)
    • libevdev.EV_ABS.ABS_PRESSUREдля давления
    • и libevdev.EV_SYN.SYN_REPORT, которые должны отправляться каждый раз, когда вы отправляете блок информации. Если вы не отправите это, ядро ​​​​не будет обрабатывать события или с очень низкой скоростью, например, 1/с.

Вы также должны убедиться, что вы ждете не менее одной секунды после включения устройства перед отправкой любого события, иначе планшет не будет распознан в будущем. Я также заметил, что часть мыши с пером не указана в xinput, пока я не отправлю первое событие. Обратите внимание, что xinputбудет перечислять два устройства, одно для кнопок, которые я предполагаю как клавиатуру, и одно как перо (с именами Tablet alone Pen (0)и Tablet alone:

.

$ xinput list
⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ ETPS/2 Elantech Touchpad                  id=17   [slave  pointer  (2)]
⎜   ↳ lircd-uinput                              id=18   [slave  pointer  (2)]
⎜   ↳ Tablet alone Pen (0)                      id=12   [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)]
    ↳ Asus Wireless Radio Control               id=7    [slave  keyboard (3)]
    ↳ Video Bus                                 id=8    [slave  keyboard (3)]
    ↳ Video Bus                                 id=9    [slave  keyboard (3)]
    ↳ Sleep Button                              id=10   [slave  keyboard (3)]
    ↳ USB2.0 HD UVC WebCam: USB2.0 HD           id=14   [slave  keyboard (3)]
    ↳ Asus WMI hotkeys                          id=15   [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=16   [slave  keyboard (3)]
    ↳ lircd-uinput                              id=19   [slave  keyboard (3)]
    ↳ Tablet alone                              id=11   [slave  keyboard (3)]

Если вы тестируете с помощью Gimp, убедитесь, что вы открываете свое программное обеспечение после того, какxinputсможет его перечислить, иначе оно не будет отображаться в списке устройств ввода, и вам нужно будет перезапустить gimp (обратите внимание, что затем вы можете перезапустить скрипт без перезапуска gimp ).Вы также хотите установить в Edit/input deviceустройство Tablet aloneна Screenи выбрать кисть, динамика которой установлена ​​примерно на Pencil Generic, как на скриншоте. Чтобы скрипт работал, вы также можете нажать Tab, чтобы снова увеличить область рисования (Tab, чтобы вернуться к обычному окну ), и масштабировать, пока вся область не будет покрыта.

enter image description here

Скрипт:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import libevdev
import time
## Some doc needed for this project
# http://www.infradead.org/~mchehab/kernel_docs_pdf/linux-input.pdf

## Some code to get inspiration from
# https://github.com/linuxwacom/input-wacom/blob/master/4.5/wacom_w8001.c

## Some doc to read at some point in my life:
# https://lwn.net/Kernel/LDD3/
# https://www.kernel.org/doc/html/v4.11/driver-api/index.html

def main(args):
    dev = libevdev.Device()
    dev.name = "Tablet alone"
    ### NB: all the following information needs to be enabled
    ### in order to recognize the device as a tablet.
    # Say that the device will send "absolute" values
    dev.enable(libevdev.INPUT_PROP_DIRECT)
    # Say that we are using the pen (not the erasor), and should be set to 1 when we are at proximity to the device.
    # See http://www.infradead.org/~mchehab/kernel_docs_pdf/linux-input.pdf page 9 (=13) and guidelines page 12 (=16), or the https://github.com/linuxwacom/input-wacom/blob/master/4.5/wacom_w8001.c (rdy=proximity)
    dev.enable(libevdev.EV_KEY.BTN_TOOL_PEN)
    dev.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER)
    # Click
    dev.enable(libevdev.EV_KEY.BTN_TOUCH)
    # Press button 1 on pen
    dev.enable(libevdev.EV_KEY.BTN_STYLUS)
    # Press button 2 on pen, see great doc
    dev.enable(libevdev.EV_KEY.BTN_STYLUS2)
    # Send absolute X coordinate
    dev.enable(libevdev.EV_ABS.ABS_X,
               libevdev.InputAbsInfo(minimum=0, maximum=32767, resolution=100))
    # Send absolute Y coordinate
    dev.enable(libevdev.EV_ABS.ABS_Y,
               libevdev.InputAbsInfo(minimum=0, maximum=32767, resolution=100))
    # Send absolute pressure
    dev.enable(libevdev.EV_ABS.ABS_PRESSURE,
               libevdev.InputAbsInfo(minimum=0, maximum=8191))
    # Use to confirm that we finished to send the informations
    # (to be sent after every burst of information, otherwise
    # the kernel does not proceed the information)
    dev.enable(libevdev.EV_SYN.SYN_REPORT)
    # Report buffer overflow
    dev.enable(libevdev.EV_SYN.SYN_DROPPED)
    try:
        uinput = dev.create_uinput_device()
        print("New device at {} ({})".format(uinput.devnode, uinput.syspath))
        # Sleep for a bit so udev, libinput, Xorg, Wayland,...
        # all have had a chance to see the device and initialize
        # it. Otherwise the event will be sent by the kernel but
        # nothing is ready to listen to the device yet. And it
        # will never be detected in the futur ;-)
        time.sleep(1) 
        # Reports that the PEN is close to the surface
        # Important to make sure xinput can detect (and list)
        # the pen. Otherwise, it won't write anything in gimp.
        uinput.send_events([
            libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
                                value=0),
            libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
                                value=1),
            libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
                                value=0),
        ])
        # Says that the pen it out of range of the tablet. Useful
        # to make sure you can move your mouse, and to avoid
        # strange things during the first draw.
        uinput.send_events([
            libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
                                value=0),
            libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
                                value=0),
            libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
                                value=0),
        ])
        print("Waiting 30s to let you:")
        print("1) open Gimp")
        print("2) Go to 'Edit/Input device' and configure the device 'Tablet alone' to 'Screen'.")
        print("3) Save and close the pop up")
        print("4) Create a new file (Ctrl-N)")
        print("5) Zoom and press 'tab' to have a drawing surface coverint most of the screen.")
        print("6) Switch to brush using 'p' key.")
        time.sleep(25)

        pc = 0
        direc = +1
        already_pressed_one = False
        for i in range(250):
            pc_ = pc/100
            val_x = int(pc_*10000 + (1-pc_)*17767)
            val_y = int(pc_*5000 + (1-pc_)*22767)
            val_pres = int(pc_*10 + (1-pc_)*6000)
            print("Will send: x={}, y={}, press={} (pc={})".format(
                val_x,
                val_y,
                val_pres,
                pc))
            uinput.send_events([
                libevdev.InputEvent(libevdev.EV_ABS.ABS_X,
                                    value=val_y),
                libevdev.InputEvent(libevdev.EV_ABS.ABS_Y,
                                    value=val_y),
                libevdev.InputEvent(libevdev.EV_ABS.ABS_PRESSURE,
                                    value=val_pres),
                libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
                                    value=1),
                libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS,
                                    value=0),
                libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS2,
                                    value=0),
                libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
                                    value=1),
                libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
                                    value=0),
            ])
            pc += direc
            if not already_pressed_one:
                print("Press!")
                uinput.send_events([
                    # Pen close to device
                    libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
                                        value=1),
                    libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
                                        value=1),
                    libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
                                        value=0),
                ])                
                already_pressed_one = True
            if pc >= 100 or pc <=0 :
                print("Release click.")
                uinput.send_events([
                    libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
                                        value=0),
                    # Pen outside of the position
                    libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
                                        value=0),
                    libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
                                        value=0),
                ])
                if pc >= 100:
                    pc = 100
                    direc = -1
                if pc <= 0:
                    pc = 0
                    direc = +1
                time.sleep(5)
                print("Press!")
                uinput.send_events([
                    # Pen close to device
                    libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
                                        value=1),
                    libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
                                        value=1),
                    libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
                                        value=0),
                ])
                already_pressed_one = True
            time.sleep(0.1)

    except KeyboardInterrupt:
        pass
    except OSError as e:
        print(e)


if __name__ == "__main__":
    if len(sys.argv) > 2:
        print("Usage: {}")
        sys.exit(1)
    main(sys.argv)

Обратите внимание, что теперь xinput test также отображает давление:

$ xinput test 12
motion a[0]=4151295 a[1]=4151295 a[2]=241 
motion a[0]=4060671 a[1]=4060671 a[2]=226 
motion a[0]=3969535 a[1]=3969535 a[2]=211 
motion a[0]=3878399 a[1]=3878399 a[2]=196 
motion a[0]=3787775 a[1]=3787775 a[2]=181 
motion a[0]=3696639 a[1]=3696639 a[2]=166 
motion a[0]=3605503 a[1]=3605503 a[2]=151 
motion a[0]=3514879 a[1]=3514879 a[2]=137 
motion a[0]=3423743 a[1]=3423743 a[2]=122 
motion a[0]=3332607 a[1]=3332607 a[2]=107 
motion a[0]=3241983 a[1]=3241983 a[2]=92 
motion a[0]=3150847 a[1]=3150847 a[2]=77 
motion a[0]=3059711 a[1]=3059711 a[2]=62 
motion a[0]=2969087 a[1]=2969087 a[2]=47 
motion a[0]=2877951 a[1]=2877951 a[2]=32 
motion a[0]=2650623 a[1]=2650623 a[2]=17 
button release 1

1
19.10.2020, 19:18
1 ответ

Простой и краткий ответ заключается в том, что если вы не сделаете history -cперед history -r, вы прочтете историю дважды .

Последняя команда (и ее номер )задаются с помощьюfc -l -1:

$ fc -l -1

19131    clear

Если вы снова прочитаете файл истории , вы продублируете большую часть истории (в памяти, а не в файле):

$ history -r; fc -l -1

38319    fc -l -1

Это причина иметь и использовать history -c.

пустая история

What then happens is that a new pane in tmux has completely empty history. The workaround for that must be very simple: just execute

history -r

И вся история в файле истории снова появится в памяти.

0
18.03.2021, 23:20

Теги

Похожие вопросы