Why XGrabKey generates extra focus

Does anyone know an xlib function to trap a keypress event without losing the original focus? How to get rid of it?

(or "to use XGrabKey() without generating Grab-style focusout"?)

(or "How to get rid of NotifyGrab and NotifyUngrab focus events at system level?)

The XGrabKey will lose focus on key pressed and restore focus on key released.

And I want to trap the keypress without leak it to the original window (just as XGrabKey can do it).

References:

  • ...XGrabKey will steal focus... https://bugs.launchpad.net/gtkhotkey/+bug/390552/comments/8

  • ...The program receives control to do something in response to the key combination. Meanwhile, the program has been temporarily focused... During XGrabKey(board), discover which window had been focused

  • ...The XGrabKeyboard function actively grabs control of the keyboard and generates FocusIn and FocusOut events... http://www.x.org/archive/X11R6.8.0/doc/XGrabKeyboard.3.html#toc3

  • ...I can't see a way to provide metacity's current desktop changin behavior (changing and showing the popup dialog at the same time) without causing a Grab-type focus out on the window... https://mail.gnome.org/archives/wm-spec-list/2007-May/msg00000.html

  • ...Fullscreen mode should not exit on FocusOut events with NotifyGrab... https://bugzilla.mozilla.org/show_bug.cgi?id=578265

  • grabbing keyboard doesnt allow changing focus ... grabbing keyboard doesnt allow changing focus

  • Focus Events Generated by Grabs (both the active grab of XGrabKeyboard and the passive grab of XGrabKey) http://www.x.org/releases/X11R7.6/doc/libX11/specs/libX11/libX11.html#Focus_Events_Generated_by_Grabs

  • the XGrabKey source code: http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/GrKey.c maybe we could modify this to get rid of focus-out events?

  • there is "DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);" in ActivateKeyboardGrab(): http://cgit.freedesktop.org/xorg/xserver/tree/dix/events.c

  • I'm writting a one-keystroke to keys-combination(and mouse movement) mapping software:https://code.google.com/p/diyism-myboard/

    I have realized it in Windows with RegisterHotKey() and UnRegisterHotKey(): https://code.google.com/p/diyism-myboard/downloads/detail?name=MyBoard.pas

    And i want to migrate it into Linux with XGrabKey() and XUngrabKey(): https://code.google.com/p/diyism-myboard/downloads/detail?name=myboard.py

    I have created $10 bounty to resolve this problem. We need more backers to place bounties. https://www.bountysource.com/issues/1072081-right-button-menu-flashes-while-jkli-keys-move-the-mouse-pointer


    I looked at global hotkeys back in the early 90s for Irix, ultrix and solaris, as it had been easy to do on my Acorn BBC computer. Eventually we decided on solving this in a non-portable way on a level below xlib with some proprietary code. Since our software installation needed as superuser priviliges anyway, we were able to insert the appropriate software hooks as daemons.

    For Linux (nowadays) you should probably look for a software solution by processing the keyboard event on the os level. I would start with having a look here: http://code.google.com/p/logkeys/

    A more generic solution would be to have a small PC board with USB in and USB out, which acts to the computer as a mouse and keyboard and translates the keyboard keys as necessary. But this would not be so flexible if you want to change the mapping often.


    My current code(from 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()
    

    When i press "shift" key, the focus lost, and when i release it, the focus come back.


    Looks like XQueryKeymap will sort you. See below for C++ source code I found:

    /* 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 startednnInfo about X11 connection:n");
     printf(" The display is::%sn",XDisplayName((char*)display_name));
     printf(" Width::%dtHeight::%dn",
     DisplayWidth(display_name,screen),
     DisplayHeight(display_name,screen));
     printf(" Connection number is %dn",connection);
    
     if(depth == 1)
      printf(" You live in prehistoric timesn");
     else
      printf(" You've got a coloured monitor with depth of %dn",depth);
    
     printf("nnLogging started.nn");
    
     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);
    }
    

    Note, this isn't tested code, nor is it mine -- I merely found it on the Internet.

    链接地址: http://www.djcxy.com/p/18434.html

    上一篇: 国际键盘如何与JavaScript键盘事件一起使用?

    下一篇: 为什么XGrabKey会产生额外的焦点