LINUX.ORG.RU

Xlib, как правильно послать клик мышкой в окно

 , ,


0

1

Доброго времени суток,

есть id окна, есть координаты, нужно в это окно послать клик мышкой по данным координатам.

Создаю своё окно, указываю ему в параметрах

event_mask=ButtonPressMask

А при вызове createWindow указываю маску CWEventMask.

Далее отслеживаю события в своём окне, при событии ButtonPress посылаю сигнал клика в другое окно:

case ButtonPress: xEvent.xbutton.window = targetWindowId;

xEvent.type = ButtonPress; XSendEvent (d, targetWindowId, False, ButtonPressMask, &xEvent);

nanosleep(&clickDelay, NULL);

xEvent.type = ButtonRelease; XSendEvent (d, targetWindowId, False, ButtonReleaseMask, &xEvent);

Проблемы: - Разным окнам задержка в clickDelay нужна разная, кому то меньше кому то больше. - Для некоторых окон пришлось использовать XWarpPointer, ждать и только потом клик слать. - Но некоторым окнам и этого было мало, пришлось MotionEvent посылать. - И всё равно остались окна, которым по барабану. - Так же есть окна, например netbeans, в которых элементы меню работают хорошо, а поле редактора либо вообще не принимает клик, либо в одном и том же месте.

Вопросы: - Как правильно послать клик мышкой окну с известным id? - Если провести по окну приложения, которое не в фокусе курсором, то там где курсор попадает на элементы меню, эти элементы реагируют, а если я в своём окне отлавливаю MotionNotify, и пересылаю его другому окну, то они не подсвечаиваются, хотя xev показывает что все события отлично доходят, почему так?



Последнее исправление: awpe (всего исправлений: 1)
Ответ на: комментарий от Zubok

Я не понимаю ничего. Я комментировал проблему, при которой частично закрытые окна не получают события по нажатию мышки. Это событие «глотает» приложение, которое находится поверх. Можешь проверить это, наложив два одинаковых окна приложения (два раза запустить одно приложение) друг на друга и посылая клик нижнему. Несмотря на указанный window id нижнего, событие получит верхнее окно, которое тебя не интересует. Это легко проверяется xdotool-ом.

Это всё я понял и прочувствовал втч и с помощью xdotool'а, вопрос про system-wide мониторинг нажатых клавиш клавиатуры, и граббинг мыши(тача) для окна.

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

вопрос про system-wide мониторинг нажатых клавиш клавиатуры, и граббинг мыши(тача) для окна.

Вот, кстати, конкретно мониторинг нажатых клавиш клавиатуры можно попробовать сделать, вызвав XSelectInput на окно root. По идее должно работать.

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

Ну как и было сказано в документации, только когда рут под фокусом, на другие окна не распространяется. Только если пройти по дереву и на каждое окно повесить XSelectInput, видимо на этом придётся остановится, так как это проще и прозрачнее чем создавать callback для X Record Extension и писать все события в очередь, потом эту очередь проверять на наличие сочетаний...

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

Надо попробовать, я так понял что XSelectInput только для окна с фокусом работает.

А как, по-твоему, оконный менеджер перехватывает свои комбинации? Он первым получает все события клавиатуры, а потом уже приложения. Вот прямо сейчас я назначил кнопку «a» на оконный менеджер. Результат: активное приложение больше букву «a» не получает вообще. Оконный менеджер первый ее забрал.

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

А как ты пытался букву «а» получить? Через XGrabKey или XSelectInput?

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

пройти по дереву и на каждое окно повесить XSelectInput

И появление новых окон отслеживать, которых не было до XQueryTree

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

Еще можешь попробовать

$ xinput --test <id клавиатуры, увидеть можно по xinput --list>

Оно и мышку покажет, если укажешь ее id

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от awpe

CreateNotify называется, да... :)

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

На root window повесить при помощи XSelectInput либо MapNotify/UnmapNotify, либо CreateNotify/DestroyNotify, чтобы апдейтить дерево. Но вообще идея с деревом - это какое-то чесание левого уха правой рукой.

UPD. что-то типа такого

    dpy = XOpenDisplay(NULL);
    root = DefaultRootWindow(dpy);
    XSelectInput(dpy, root, SubstructureNotifyMask);

    while (1) {
        XNextEvent(dpy, &event);

        /* Слушаем сообщения */
    }
Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 4)
Ответ на: комментарий от Zubok

Но вообще идея с деревом - это какое-то чесание левого уха правой рукой.

С деревом, конечно, есть и профит, на первый взгляд: можно узнать, какому окну пришло сообщение. Если просто устройства ввода слушать, то идут обезличенные координаты и коды кнопок, а если слушать события окон, то ты знаешь всегда, какое окно слушаешь. И даже можешь узнать, что вот эти последовательности пошли в окно FF, а эти — в терминал. Хотя надо будет уточнить, какой идентификатор окна придет в событиях...

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 2)
Ответ на: комментарий от Zubok

С деревом, конечно, есть и профит, на первый взгляд

Хотя... в событиях XDeviceMotionEvent, XDeviceKeyEvent, XDeviceButtonEvent и др. из X Input Extension тоже в событии идет event window (поле event), но там, похоже, сообщается окно, над которым указатель находится. Надо проверить.

http://www.x.org/archive/X11R7.6/doc/inputproto/XIproto.txt

3.1 Button, Key, and Motion Events

               DeviceKeyPress
               DeviceKeyRelease
               DeviceButtonPress,
               DeviceButtonRelease
               DeviceMotionNotify
                       device: CARD8
                       root, event: WINDOW
                       child: Window or None
                       same-screen: BOOL
                       root-x, root-y, event-x, event-y: INT16
                       detail: <see below>
                       state: SETofKEYBUTMASK
                       time: TIMESTAMP

   These events are generated when a key, button, or valuator
   logically changes state. The generation of these logical
   changes may lag the physical changes, if device event
   processing is frozen. Note that DeviceKeyPress and
   DeviceKeyRelease are generated for all keys, even those mapped
   to modifier bits. The “source” of the event is the window the
   pointer is in. The window with respect to which the event is
   normally reported is found by looking up the hierarchy
   (starting with the source window) for the first window on which
   any client has selected interest in the event. The actual
   window used for reporting can be modified by active grabs and
   by the focus window.The window the event is reported with
   respect to is called the “event” window.
Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 3)
Ответ на: комментарий от Zubok

Мне для клавиш окно совсем не интересно, мне сам факт, что были нажаты такие то клавиши интересен, и от окна в фокусе ничего не должно зависеть...

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

Мне для клавиш окно совсем не интересно, мне сам факт, что были нажаты такие то клавиши интересен, и от окна в фокусе ничего не должно зависеть...

Так речь я веду не о зависимости от окна, а от знания, от какого окна приходило событие. Ты можешь не обрабатывать эту информацию, но она может быть полезна. Просто за компанию в событии приходит параметр event window.

И посмотри, как сделано в утилите xinput (параметры --test и --test-xi2). Там предельно все просто. Получишь коды нажатых клавиш вообще вне зависимости от всего, но с особенностью: модификаторы тоже будут коды клавиш слать. В xinput, как следует из названия, используется X Input (1 и 2).

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

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

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

Интересно, можно послать на устройство какой нибудь сигнал и проверить ответ, чтобы знать что устройство не подвисло?

Например

char buf[] = "что то на что ответит не зависшее устройство";
write(deviceFd, buf, sizeof(buf));
int res = pselect(...);
if (res == -1)
{
//reset device
}

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

только второй версии, хотел без расширений решить всё, но видимо так оптимальней будет...

В качестве каприза можно попробовать.

Интересно, можно послать на устройство какой нибудь сигнал и проверить ответ, чтобы знать что устройство не подвисло?

А что значит, подвисло? Ну, собсна, в X Input есть список устройств ввода и их свойства. Если ты что-то от USB отключаешь, то устройство пропадает. Вот и проверили. С PS/2 и COM, врочем, не уверен, что пройдет фокус. А так ядро сообщает, что что-то отключилось, а X-сервер отрабатывает. Но вот что такое «подвисшее» состояние... Драйвер завис?

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

Имеем хаб usb2.0, на нём большой светодиод, в него включено несколько устройств, предполагается что он активный, выключаем питание из розетки, включаем подсветку на клавиатуре - мышь светится, в списке устройств присутствует, по пока не подашь внешнее питание на хаб, курсор на движения мыши не реагирует, как этот момент проверить?

Я уже второй день ищу как с помощью xinput2 слушать устройство... Все примеры втч код из GTK и QT, предполагает делать так

XISelectEvents(...)
Для каждого виджета в окне, также в нескольких xinput1->xinput2 conversion guide, предлагают вешать прослушку на окно, печальный опыт с XSelectEvent, подсказывает что даже если повесить на корневое окно, пока фокус не нём не появится ничего прослушать не получится, на данный момент итог такой:

  • Идём по дереву и вешаем на каждое окно XSelectEvent, отслеживаем создание новых окон и на них тоже ставим прослушку
  • Не пользуемся xinput2, но используя xinput1 слушаем устройство вне зависимости от окна
    XOpenDevice(...)

Неужели xinput2 не предусматривает прослушивание устройства вне зависимости от окна?

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

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

awpe
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.