LINUX.ORG.RU

Есть ли возможность управлять из одного процесса вводом для других процессов?

 


0

1

Мне захотелось решить задачу в одной игре шутере (Arena Breakout), которая заключаеться в том чтобы максимально быстро беззвучно передвигаться. Для этого там нужно войти в режим тихой ходьбы и двигаться с прерываниями. Если просто зажать кнопку ходьбы, то всё равно будет издаваться минимальный звук. Так вот мне захотелось передвигаться беззвучно на зажатие сочетание клавиш ctrl+w/a/s/d (То есть я хочу чтобы при зажатии клавишь ctrl+w/a/s/d игра думала что я циклично зажимаю w/a/s/d на 0,1 секунду, затем отпускаю w/a/s/d на 0,1 секунду). Я думаю будет не сложно найти библиотеки которые регистрирует сочетания клавиш на фоне и эмулируют частые нажатия клавишь направлений ходьбы. Но проблема в том, что игра тоже зарегистрирует зажатие клавиш ctrl и w/a/s/d, а зажатие клавиш в игре это непрерывная ходьба, а мне надо как раз таки делать перерывы. Переназначать клавиши ходьбы для реализации логики фоновой программы мне не хотелось бы, потому что так не удобно играть. Мне бы хотелось чтоб моя фоновая программа просто делала «невидимыми» зажатия клавишь w/a/s/d при условии, что так же зажат ctrl, а затем эмулировала преривыстые нажатия w/a/s/d для игры. И тут не просто стоит задача спрятать какие-то нажатия от игры, но и спрятать сэмулированные прерывистые нажатия для самой фоновой программы чтоб её алгоритм не выполнялся снова. Так вот, расскажите, есть ли решение такой задачи? Где искать информацию об этом? Может нужен другой подход к решению, другая архетектура? Может для этого надо патчить драйвер клавиатуры или само ядро, потому что linux таких возможностей не предоставляет?

Мне известно что вышеуказанная игра недоступна под linux, но я просто привёл пример, хочу узнать как в linux решить такую задачу и решаема ли она вообще, чтобы легче было искать решение под виндой


Нифига не понял, но в линуксе спокойно пишется код, читающий input-устройство, из которого он получает коды клавиш, а дальше, он может отправлять какие угодно события/нажатия клавиш. И, то что этот код прочитает из input, достаётся только ему, другие программы не получат эти нажатия. Тут, главное, отключить автоповтор, чтобы зажатие клавиши не представлялось как куча нажатий.

mky ★★★★★
()
Ответ на: комментарий от mky

Ок, тогда выдержка без лишних контекстов что конкретно я ищу — я хочу найти способ из своей программы перехватывать нажатия клавиш, и перехватывать в том смысле, чтоб другие работающие программы, например игра, получали события нажатия тех клавиш которые я захочу и только тогда когда я захочу. А конкретно я хочу нажатие одной клавиши представить для игры как нажатие другой, то есть как я понимаю нужно спрятать первое и сэмулировать второе

А на счёт вашего решения хотелось бы информации как такую программу написать, которая обрабатывает нажатия клавиш, а дальше уже шлёт события их нажатий всем. Я не думаю что её можно просто так написать, иначе можно спокойно написать вирус который просто заблочит весь ввод с клавиатуры

Trame
() автор топика
Ответ на: комментарий от u5er

Ты предлагаешь мне задрачивать скил быстрого нажатия клавиш с умеренными таймингами? Я не хочу такого, если игра такое позволяет, то я хочу без задротсва этим пользоваться. Да и тем более у меня если часто жать кнопку шумит клава, так что я лишаюсь звуков. Настоящие читаки это челы с 500гц экранами, наушниками с позиционированием и безшумными клавами

Trame
() автор топика
Ответ на: комментарий от Trame

Я знаю только про Линукс, как написать под винду не знаю.

По Линуком программа открывает файл, соотв. клавиатуре /dev/input/eventX, где вместо X какое-то число. Потом делат ioctl EVIOCGRAB и получает монопольный доступ к событиями с этого устройства. И через механизм uinput создаёт другое псевдо устройство ввода (псевдо-клавиатуру), куда шлёт какие угодно нажатия.

struct input_event ev;
int fdi = open("/dev/input/event1", O_RDONLY);
int fdo = open(UINP, O_WRONLY|O_NONBLOCK);
// Проверка, что файлы открылися

// Всякие ioctl для fdo, типа ioctl(fdo, UI_SET_EVBIT, EV_KEY)

// Цикл ожидания с проверко, что нажатых клавиш нет

ioctl(fdi, EVIOCGRAB, 1);
// Проверка, что ioctl выполнился успешно

while(1) { // основной цикл
   sz = read(fdi, &ev, sizeof(struct input_event));
   if ( sz > 0 ) {
// Разбор события -- полей структуры ev
// Отправка нужных событий (клавиш) в fdo:
   write(fdo, &ev, sizeof(struct input_event));
}

Про uinput вам уже написали, можете гуглить, изучать примеры, как эмулировать ввод.

Отдельно можете гуглить примеры по слову EVIOCGRAB — монопольный доступ. Примеров масса, единственное, что лучше сначала в цикле ждать момента, когда не будет нажатых клавиш постоянно выполняя ioctl(fd, EVIOCGKEY), и только тогда «забирать» клавиатуру. Тогда проще обрабатывать события от клавиатуры.

Именно для ваше задачи, скорее всего, нужно будет открывать /dev/input/eventX с флагом O_NONBLOCK, чтобы не останавливаться на чтении, а отсчитывать 0,1 с и посылать нажатие/отпускание.

спокойно написать вирус

Пишите, у вируса основная проблема в том, как он распространяться будет, а не в том, что он что-то там заблокирует...

mky ★★★★★
()