diy*_*ism 37 python linux x11 xlib
有没有人知道一个xlib函数来捕获一个按键事件而不会失去原始焦点?如何摆脱它?
(或"使用XGrabKey()而不产生抓取式焦点"?)
(或"如何摆脱系统级别的NotifyGrab和NotifyUngrab焦点事件?)
XGrabKey将失去对关键按下和恢复焦点的关注.
而且我想捕获按键而不将其泄漏到原始窗口(正如XGrabKey可以做到的那样).
参考文献:
...... XGrabKey将窃取焦点... https://bugs.launchpad.net/gtkhotkey/+bug/390552/comments/8
...程序接受控制以响应键组合做某事.同时,该程序暂时关注... 在XGrabKey(董事会)期间,发现哪个窗口已经集中
... XGrabKeyboard函数主动抓取键盘控制并生成FocusIn和FocusOut事件...... http://www.x.org/archive/X11R6.8.0/doc/XGrabKeyboard.3.html#toc3
...我无法看到提供metacity当前桌面变换行为的方法(同时更改和显示弹出对话框),而不会在窗口上引起Grab类型的焦点... https://mail.gnome .ORG /档案馆/ WM说明列表/ 2007-月/ msg00000.html
...全屏模式不应退出使用NotifyGrab的FocusOut事件... https://bugzilla.mozilla.org/show_bug.cgi?id=578265
抓住键盘不允许改变焦点... 抓住键盘不允许改变焦点
Grabs生成的焦点事件(XGrabKeyboard的主动抓取和XGrabKey的被动抓取) http://www.x.org/releases/X11R7.6/doc/libX11/specs/libX11/libX11.html#Focus_Events_Generated_by_Grabs
XGrabKey源代码:http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/GrKey.c 也许我们可以修改它来摆脱焦点事件?
有"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
我想通过XGrabKey()和XUngrabKey()将其迁移到Linux: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
Ant*_*hon 12
我在90年代早期看过Irix,ultrix和solaris的全球热键,因为它在我的Acorn BBC电脑上很容易做到.最终,我们决定以低于xlib的级别以非便携方式使用一些专有代码来解决这个问题.由于我们的软件安装无论如何都需要作为超级用户权限,我们能够插入适当的软件挂钩作为守护进程.
对于Linux(现在),您应该通过在操作系统级别处理键盘事件来寻找软件解决方案.我先来看看这里:http://code.google.com/p/logkeys/
更通用的解决方案是使用带有USB输入和USB输出的小型PC板,它可以作为鼠标和键盘对计算机起作用,并根据需要翻译键盘键.但如果您想经常更改映射,这将不会那么灵活.
diy*_*ism 12
我目前的代码(来自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
我还需要在gtk上下文菜单中摆脱XGrabKeyboard:
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=libgtk2.0-0_2.24.17-0ubuntu2_i386.deb