41

元のフォーカスを失わずにキープレスイベントをトラップする xlib 関数を知っている人はいますか? それを取り除く方法は?

(または、「Grab スタイルの focusout を生成せずに 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. ...メタシティの現在のデスクトップ変更動作 (ポップアップ ダイアログの変更と表示を同時に) を提供する方法が、ウィンドウに Grab タイプのフォーカスを発生させずに提供する方法がわかりません... https://mail.gnome .org/archives/wm-spec-list/2007-May/msg00000.html

  5. ...NotifyGrab を使用した FocusOut イベントでフルスクリーン モードを終了しないでください... https://bugzilla.mozilla.org/show_bug.cgi?id=578265

  6. キーボードをつかんでもフォーカスを変更できません ... キーボードをつかんでもフォーカスを変更できません

  7. グラブによって生成されるフォーカス イベント (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/

RegisterHotKey() と UnRegisterHotKey() を使用して Windows で実現しました: 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

4

8 に答える 8

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()

「シフト」キーを押すとフォーカスが失われ、離すとフォーカスが戻ります。

于 2013-03-14T08:30:10.530 に答える
11

90 年代初頭に、Irix、ultrix、solaris のグローバル ホットキーを調べました。これは、Acorn BBC コンピューターで簡単に実行できたからです。最終的に、xlib より下のレベルで独自のコードを使用して、移植性のない方法でこれを解決することにしました。とにかく、ソフトウェアのインストールにはスーパーユーザー権限が必要だったので、適切なソフトウェアフックをデーモンとして挿入することができました。

Linux (最近) の場合は、おそらく OS レベルでキーボード イベントを処理するソフトウェア ソリューションを探す必要があります。ここを見ることから始めます:http://code.google.com/p/logkeys/

より一般的な解決策は、USB 入力と USB 出力を備えた小さな PC ボードを用意することです。これは、コンピューターに対してマウスとキーボードとして機能し、必要に応じてキーボードのキーを変換します。しかし、マッピングを頻繁に変更したい場合、これはあまり柔軟ではありません。

于 2013-03-10T13:34:37.407 に答える
5

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);
}

これはテスト済みのコードではなく、私のものでもありません。インターネットで見つけただけです。

于 2013-03-10T13:43:25.570 に答える
0

XQueryKeymapを使用してイベントを読み取り、次にXTestKeyを使用してバックスペース キー イベントを送信し、次に押したいキーを送信できます。より良い方法として、すべてのキーボード イベントのホットキーを登録し、XTestKey を使用してキー イベントを生成することができます。ところで、KDE ​​の「カスタム ショートカット」コントロール モジュールを使用すると、ショートカットを使用してキープレスを生成できます。ソースコード

于 2013-11-16T07:50:39.360 に答える
0

この質問は古いと思いますが、まだ関連性があり、xorg-server を変更するよりも移植性の高い回避策を見つけました。

基本的に、グラブ ウィンドウがアクティブにフォーカスされたウィンドウである場合、XGrabKey はフォーカス イベントを送信しません。

アクティブなウィンドウを見て、フォーカスが新しいウィンドウに変わったときにグラブをリセットすると、イベントは生成されません。PropertyNotify イベントを監視し、 _NET_ACTIVE_WINDOWwindow プロパティを調べると、その情報を取得するのにうまく機能することがわかりました。

グラブを現在アクティブなウィンドウに設定することによる有害な影響、または率直に言って、なんらかの影響はまだ見つかっていません。

于 2021-09-17T00:46:06.107 に答える