Почему XGrabKey генерирует дополнительные фокусы и фокус-события?

Кто-нибудь знает функцию xlib, чтобы уловить событие нажатия клавиши без потери первоначального фокуса? Как избавиться от него?

(или «использовать XGrabKey () без создания фокуса в стиле захвата»?)

(или «Как избавиться от событий NotifyGrab и NotifyUngrab фокус на системном уровне?)

XGrabKey потеряет фокус на нажатой клавише и восстановит фокус на выпуске ключа.

И я хочу уловить нажатие клавиши без ее утечки в исходное окно (так же, как XGrabKey может это сделать).

Рекомендации:

  1. … XGrabKey украдет фокус … https://bugs.launchpad.net/gtkhotkey/+bug/390552/comments/8

  2. … Программа получает контроль, чтобы что-то сделать в ответ на комбинацию клавиш. Между тем, программа была временно сфокусирована … Во время XGrabKey (доска), откройте, какое окно было сфокусировано

  3. … Функция XGrabKeyboard активно захватывает управление клавиатурой и генерирует события FocusIn и FocusOut … http://www.x.org/archive/X11R6.8.0/doc/XGrabKeyboard.3.html#toc3

  4. … Я не вижу способа обеспечить текущее поведение элемента управления metacity (изменение и отображение всплывающего диалогового окна в одно и то же время), не вызывая фокус Grab-типа в окне … https: //mail.gnome .org / архив / WM-спец-лист / 2007-май / msg00000.html

  5. … Полноэкранный режим не должен выходить из событий FocusOut с NotifyGrab … https://bugzilla.mozilla.org/show_bug.cgi?id=578265

  6. захватывающая клавиатура не позволяет менять фокус … захват клавиатуры не позволяет менять фокус

  7. Фокус-события, созданные с помощью Grabs (как активный захват XGrabKeyboard, так и пассивный захват XGrabKey) http://www.x.org/releases/X11R7.6/doc/libX11/specs/libX11/libX11.html#Focus_Events_Generated_by_Grabs

  8. исходный код XGrabKey: http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/GrKey.c, возможно, мы могли бы изменить это, чтобы избавиться от событий фокуса?

  9. есть «DoFocusEvents (keybd, oldWin, grab-> window, NotifyGrab)»; в ActivateKeyboardGrab (): http://cgit.freedesktop.org/xorg/xserver/tree/dix/events.c

Я нажимаю однократное нажатие на картографическое программное обеспечение для комбинации клавиш (и мыши): https://code.google.com/p/diyism-myboard/

Я понял это в Windows с помощью RegisterHotKey () и UnRegisterHotKey (): https://code.google.com/p/diyism-myboard/downloads/detail?name=MyBoard.pas

И я хочу перенести его в Linux с помощью XGrabKey () и XUngrabKey (): https://code.google.com/p/diyism-myboard/downloads/detail?name=myboard.py

Я создал 10 долларов США для решения этой проблемы. Нам нужно больше покровителей, чтобы размещать награды. https://www.bountysource.com/issues/1072081-right-button-menu-flashes-while-jkli-keys-move-the-mouse-pointer

  • глобальный захват, игнорирование и отправка ключей с помощью python xlib, распознавание поддельного ввода
  • Прослушивание событий клавиатуры без их захвата?
  • Глобальная привязка клавиш на X с использованием Python gtk3
  • Захват и интерпретация события XI2 RawKeyPress с помощью python
  • Как я могу отслеживать события мыши с помощью Python Xlib вместо их захвата?
  • Как установить Python Xlib с помощью пипа?
  • Как я могу использовать python xlib для создания одного нажатия клавиши?
  • Python: Xlib - Как я могу поднимать (выводить вверх) окна?
  • 7 Solutions collect form web for “Почему XGrabKey генерирует дополнительные фокусы и фокус-события?”

    Я посмотрел на глобальные горячие клавиши еще в начале 90-х для Irix, ultrix и solaris, поскольку это было легко сделать на моем компьютере Acorn BBC. В конце концов мы решили решить это не переносимым образом на уровне ниже xlib с некоторым проприетарным кодом. Так как наша установка программного обеспечения была необходима как привилегированный суперпользователь, мы смогли вставить соответствующие программные крючки в качестве демонов.

    Для Linux (в настоящее время) вы, вероятно, должны искать программное решение, обрабатывая событие клавиатуры на уровне os. Я бы начал с просмотра здесь: http://code.google.com/p/logkeys/

    Более общим решением было бы иметь небольшую плату с USB и USB-выходом, которая действует на компьютер как мышь и клавиатура и при необходимости переводит клавиши клавиатуры. Но это не будет настолько гибким, если вы хотите часто менять отображение.

    Мой текущий код (из http://diyism-myboard.googlecode.com/files/myboard.py ):

    disp=Display() screen=disp.screen() root=screen.root def grab_key(key, mod): key_code=string_to_keycode(key) #3rd: bool owner_events, 4th: pointer_mode, 5th: keyboard_mode, X.GrabModeSync, X.GrabModeAsync root.grab_key(key_code, mod, 0, X.GrabModeAsync, X.GrabModeAsync) root.grab_key(key_code, mod|X.LockMask, 0, X.GrabModeAsync, X.GrabModeAsync) #caps lock root.grab_key(key_code, mod|X.Mod2Mask, 0, X.GrabModeAsync, X.GrabModeAsync) #num lock root.grab_key(key_code, mod|X.LockMask|X.Mod2Mask, 0, X.GrabModeAsync, X.GrabModeAsync) def main(): grab_key('Shift_L', X.NONE) grab_key('Shift_R', X.NONE) while 1: evt=root.display.next_event() if evt.type in [X.KeyPress, X.KeyRelease]: #ignore X.MappingNotify(=34) handle_event(evt) if __name__ == '__main__': main() 

    Когда я нажимаю клавишу «shift», фокус теряется, и когда я его отпускаю, фокус возвращается.

    Похоже, XQueryKeymap сортирует вас. Ниже для исходного кода C ++ я нашел :

     /* compile with g++ keytest.cpp -LX11 -o keytest */ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/time.h> double gettime() { timeval tim; gettimeofday(&tim, NULL); double t1=tim.tv_sec+(tim.tv_usec/1000000.0); return t1; } int main() { Display *display_name; int depth,screen,connection; display_name = XOpenDisplay(NULL); screen = DefaultScreen(display_name); depth = DefaultDepth(display_name,screen); connection = ConnectionNumber(display_name); printf("Keylogger started\n\nInfo about X11 connection:\n"); printf(" The display is::%s\n",XDisplayName((char*)display_name)); printf(" Width::%d\tHeight::%d\n", DisplayWidth(display_name,screen), DisplayHeight(display_name,screen)); printf(" Connection number is %d\n",connection); if(depth == 1) printf(" You live in prehistoric times\n"); else printf(" You've got a coloured monitor with depth of %d\n",depth); printf("\n\nLogging started.\n\n"); char keys_return[32]; while(1) { XQueryKeymap(display_name,keys_return); for (int i=0; i<32; i++) { if (keys_return[i] != 0) { int pos = 0; int num = keys_return[i]; printf("%.20f: ",gettime()); while (pos < 8) { if ((num & 0x01) == 1) { printf("%d ",i*8+pos); } pos++; num /= 2; } printf("\n"); } } usleep(30000); } XCloseDisplay(display_name); } 

    Заметьте, это не проверенный код, и он не мой – я просто нашел его в Интернете.

    Наконец, как вы знаете, Linux означает свободу, я изменил xserver, чтобы избавиться от захвата в стиле захвата:

     sudo apt-get build-dep xorg-server apt-get source xorg-server cd xorg-server-* #modify or patch dix/events.c: comment off "DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);" in ActivateKeyboardGrab(), comment off "DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);" in DeactivateKeyboardGrab() sudo apt-get install devscripts debuild -us -uc #"-us -uc" to avoid the signature step cd .. sudo dpkg --install xserver-xorg-core_*.deb #clear dependencies: sudo apt-mark auto $(apt-cache showsrc xorg-server | grep Build-Depends | perl -p -e 's/(?:[\[(].+?[\])]|Build-Depends:|,|\|)//g') sudo apt-get autoremove 

    И мне также нужно избавиться от XGrabKeyboard в контекстном меню gtk:

     sudo apt-get build-dep gtk+2.0 apt-get source gtk+2.0 cd gtk+2.0-* #modify or patch it: add "return TRUE;" in first line of popup_grab_on_window() of gtk/gtkmenu.c dpkg-source --commit debuild -us -uc #"-us -uc" to avoid the signature step, maybe need: sudo apt-get install devscripts cd .. sudo dpkg --install libgtk2.0-0_*.deb #clear dependencies: sudo apt-mark auto $(apt-cache showsrc gtk+2.0 | grep Build-Depends | perl -p -e 's/(?:[\[(].+?[\])]|Build-Depends:|,|\|)//g') sudo apt-get autoremove 

    Теперь myboard.py работает хорошо.

    Если вы используете редакцию ubuntu raring-updates, вы можете попробовать:

    https://code.google.com/p/diyism-myboard/downloads/detail?name=xserver-xorg-core_1.13.3-0ubuntu6.2_i386.deb

    а также:

    https://code.google.com/p/diyism-myboard/downloads/detail?name=libgtk2.0-0_2.24.17-0ubuntu2_i386.deb

    У меня есть идея, что я уверен, что это сработает, но я должен лечь спать и не могу проверить ее сам, и это не очень, так как я не думаю, что есть какой-то способ сделать то, что вы хочу в X. Вот шаги, которые я имею в виду. Короче: отключите клавиатуру в X, прочитайте события с нижнего уровня api и выборочно подайте их на X самостоятельно. Вы должны отключить клавиатуру в X, потому что в противном случае вы можете посмотреть событие, но не останавливать его; вы читали бы его вместе с X, а не перехватывали бы его.

    Итак, вот оно разбито:

    1) Запустите xinput -list чтобы использовать клавиатуру X

    2) Запустите xinput list-props чтобы найти свойство Device Enabled

    3) Запустите xinput set-prop id prop 0 чтобы отключить устройство в X:

     xinput -list xinput list-props 12 # 12 is the id of the keyboard in the list... (example # btw) xinput set-prop 12 119 0 # 119 is the "Device Enabled" prop, we turn it off 

    Я не знаю, как xinput работает на уровне xlib, я просто вызываю его в оболочку для простоты реализации.

    4) Открыть /dev/input/eventX , где X – клавиатурное устройство. Я бы действительно искал имя (данное в xinput -list) в / dev / input / by-id и открыл его таким образом. Вероятно, в какой-то момент это потребует root, так как разрешения на них, как правило, довольно ограничительные.

    5) Прочитайте ввод с клавиатуры:

    Формат данных из входных событий:

     struct input_event { int tv_sec; // time of the event int tv_usec; // ditto ushort type; // == 1 for key event ushort code; // key code, not the same as X keysyms, you should check it experimentally. 42 is left shift on mine, 54 is right shift int value; // for keys, 1 == pressed, 0 == released, 2 == repeat } 

    ints – 32 бит, ushorts – 16 бит. Поскольку вас интересует только ввод с клавиатуры, вы можете сделать это довольно просто:

    • читать и игнорировать 8 байтов.

    • следующий байт должен быть 1, затем следующий – 0. Если нет, пропустите это событие

    • Следующий байт – это маленький конец кода ключа, и поскольку есть <255 ключей, это достаточно хорошо, поэтому

    • пропустите следующий байт.

    • прочитайте следующий байт, чтобы узнать, нажата ли она или выпущена

    • пропустить следующие три байта

    6) Когда вы получаете событие, которое вас интересует в ловушке, обработайте его самостоятельно. В противном случае используйте XSendEvent, чтобы отправить его на X, чтобы его можно было обрабатывать в обычном режиме. Сопоставление аппаратного кода, который вы получаете от / dev / input, к соответствующему keyym, может быть трюком, но я уверен, что в xlib есть функция, чтобы помочь с этим.

    7) goto 5 и цикл, пока вы не закончите

    8) Убедитесь, что вы все вернули, как это было, когда вы выходите, или вы можете сломать входной сигнал клавиатуры пользователя на X!

    Я бы предложил протестировать это с помощью второй клавиатуры usb, вы можете отключить и слушать клавиатуру независимо друг от друга с помощью / dev / input и xinput, поэтому, если вы потерпите крах, у вас все еще есть первая клавиатура и работает нормально. (На самом деле, я думаю, было бы здорово умышленно сделать это со второй клавиатурой, удвоить горячие клавиши!)

    Но да, нуждаясь в корне и потенциально оставляя клавиатуру «отстраненной» от X, совсем не красивы, и что пересылка с помощью SendKey может быть проще сказать, чем сделать, но я уверен, что это сработает и даст вам максимальную гибкость ,

    Для написания программного обеспечения для сопоставления клавиш (ярлыка) также смотрите библиотеку ввода- libtermkey , написанную на C, которая распознает информацию о положении мыши / кнопке мыши в стиле XTerm, специальные клавиши (такие как стрелки и функциональные клавиши), включая " модифицированных "клавиш, таких как Ctrl-Left .

    Существует, например, POE::Wheel::TermKey , «асинхронная Perl-оболочка вокруг библиотеки libtermkey , которая предоставляет абстрактный способ чтения событий нажатия клавиш в терминальных программах».

    Вы можете использовать XQueryKeymap для чтения событий, тогда вы можете использовать XTestKey для отправки события ключевого слова backspace, а затем клавиши, которую вы хотите нажать. Лучше, вы можете зарегистрировать горячие клавиши для всех событий клавиатуры, а затем сгенерировать ключевое событие с помощью XTestKey. BTW, модуль управления «Custom Shortcuts» KDE позволяет использовать ярлыки для генерации нажатий клавиш. Исходный код .

    Python - лучший язык программирования в мире.