12

USB 接続を介してタッチ イベントを提供するデバイスに接続されている、Linux/X11 を実行する組み込みデバイスがあります。このデバイスは、標準のポインター/マウス入力の形式としては認識されません。私がやろうとしているのは、外部デバイスがイベントを報告したときにマウスイベントを X11 に「注入」する方法を見つけることです。

そうすることで、私のアプリケーション (Gtk+ を使用して C で記述) が Gtk+ 呼び出しでマウスの押下を偽造する必要がなくなります。

これができれば、私の Gtk+ アプリケーションは、タッチ イベントを生成するデバイスを認識したり気にしたりする必要がなくなります。アプリケーションには、標準のマウス イベントとして表示されます。

X11に合成マウスイベントを挿入する方法を知っている人はいますか?

現在、私は次のことを行っていますが、これは機能しますが、最適ではありません。

GtkWidget *btnSpin;     /* sample button */

gboolean buttonPress_cb( void *btn );
gboolean buttonDePress_cb( void *btn );


/*  make this call after the device library calls the TouchEvent_cb() callback
    and the application has determined which, if any, button was touched

    In this example we are assuming btnSpin was touched.

    This function will, in 5ms, begin the process of causing the button to do it's 
    normal animation ( button in, button out effects ) and then send the actual
    button_clicked event to the button.
*/
g_timeout_add(5, (GSourceFunc) buttonPress_cb, (void *)btnSpin);


/*  this callback is fired 5ms after the g_timeout_add() function above.
    It first sets the button state to ACTIVE to begin the animation cycle (pressed look)
    And then 250ms later calls buttonDePress_cb which will make the button look un-pressed
    and then send the button_clicked event.
*/    
gboolean buttonPress_cb( void *btn )
{

    gtk_widget_set_state((GtkWidget *)btn, GTK_STATE_ACTIVE);
    g_timeout_add(250, (GSourceFunc) buttonDePress_cb, btn);


    return( FALSE );
}

/*  Sets button state back to NORMAL ( not pressed look )
    and sends the button_clicked event so that the registered signal handler for the
    button can be activated
*/
gboolean buttonDePress_cb( void *btn )
{

    gtk_widget_set_state( btn, GTK_STATE_NORMAL);
    gtk_button_clicked( GTK_BUTTON( btn ));

    return( FALSE );
}
4

4 に答える 4

10

いくつかの方法があります。

  1. を使用しXSendEventます。警告: 一部のアプリケーション フレームワークは、 で送信されたイベントを無視しますXSendEvent。Gtk+ はそうではないと思いますが、チェックしていません。
  2. とを使用XTestFakeMotionEventXTestFakeButtonEventます。X サーバーには XTest 拡張機能が必要です。
  3. マウス/タッチパッドとして表示されるように、デバイスのカーネル ドライバーを作成します。
于 2012-04-25T16:25:00.180 に答える
9

Linux入力システムには、uinputと呼ばれる入力デバイスのユーザースペース実装のための機能があります。デバイスのコールバックライブラリを使用して入力イベントをカーネルに送信するバックグラウンドプログラムを作成できます。Xサーバー(evdev入力モジュールを使用していると仮定)は、他のマウスイベントと同じようにこれらを処理します。

これをかなり簡単にするlibsuinputというライブラリがあります。モデルとして使用できるマウス入力プログラムの例も含まれています。ただし、デバイスはタッチベースのデバイスであるため、相対軸(REL_X、REL_Y)ではなく絶対軸(ABS_X、ABS_Y)を使用する可能性があります。

于 2012-04-25T19:01:52.623 に答える
6

/dev/input/eventX最もクールなことは、evdev プロトコルを話すファイルを作成するデバイス ドライバーをカーネル内に実装することです。Linux Device Driversこれをやりたいと思ったら、という本を読むことをお勧めします。この本はウェブ上で無料で入手できます。

これをユーザー空間で行いたい場合は、Xlib (または XCB) を使用することをお勧めします。プレーンな Xlib (C 言語) では、X Test Extensionまたはを使用できますXSendEvent()

xautomation パッケージの xte というバイナリもあります (Debian ではsudo apt-get install xautomation、次にman xte)。xteは非常に使いやすく、そのソース コードを見て、X Test Extension の使用方法を学習することもできます。

ポインター:

于 2012-04-25T16:27:26.150 に答える
1

もう少し調査した結果、Gtk+ は、X11 コーディングを深く掘り下げたり、カーネル ドライバーを作成したりすることなく、私が望むことを実行できる GDK ライブラリを使用しているようです。ただし、時間があれば、Linux カーネル マウス ドライバーを書きたいと思っています。

GDK 2リファレンスマニュアルを使用すると、次のことができることがわかりました。

の型gtk_event_put()を追加するために使用しますGdkEventGdkEventButton

a の構造GdkEventButtonは次のとおりです。

struct GdkEventButton {
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  guint32 time;
  gdouble x;
  gdouble y;
  gdouble *axes;
  guint state;
  guint button;
  GdkDevice *device;
  gdouble x_root, y_root;
};

これらのフィールドのほとんどは、次の例外を除いて簡単に入力できます。

gdouble x;
    the x coordinate of the pointer relative to the window.

gdouble y;
    the y coordinate of the pointer relative to the window.

GdkDevice *device;
    the device where the event originated.

gdouble x_root;
    the x coordinate of the pointer relative to the root of the screen.

gdouble y_root;
    the y coordinate of the pointer relative to the root of the screen.

画面のルート座標をウィンドウの相対座標に変換する方法を調査する必要があります。

*device- これは拡張入力デバイス用であるため、このフィールド ( NULL に設定) を使用する必要があるかどうかわかりません。ただし、ここで有効なデバイスが必要な場合は、gdk_devices_list()を使用できるはずです

于 2012-04-25T18:47:00.410 に答える