2012-04-25 25 views
11

Tôi có thiết bị nhúng chạy Linux/X11 được kết nối với thiết bị cung cấp sự kiện chạm qua kết nối USB. Thiết bị này không được nhận dạng dưới dạng đầu vào con trỏ/chuột chuẩn. Những gì tôi đang cố gắng làm là tìm một cách để "tiêm" các sự kiện chuột vào X11 khi thiết bị bên ngoài báo cáo một sự kiện.Cách chèn các sự kiện chuột tổng hợp vào hàng đợi đầu vào X11

Làm như vậy sẽ xóa nhu cầu đăng ký của tôi (được viết bằng C bằng Gtk +) cho máy ép chuột giả với các cuộc gọi Gtk +.

Nếu điều này có thể được thực hiện, ứng dụng Gtk + của tôi sẽ không cần phải biết hoặc quan tâm đến thiết bị tạo sự kiện chạm. Nó sẽ chỉ xuất hiện với ứng dụng như các sự kiện chuột chuẩn.

Bất kỳ ai biết cách chuyển các sự kiện chuột tổng hợp thành X11?

Hiện tại tôi đang thực hiện các thao tác sau, nhưng không phải là tối ưu.

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

Trả lời

9

Hệ thống đầu vào Linux có cơ sở cho việc triển khai không gian người dùng của các thiết bị đầu vào được gọi là uinput. Bạn có thể viết một chương trình nền sử dụng thư viện gọi lại của thiết bị để gửi các sự kiện đầu vào cho hạt nhân. Máy chủ X (giả sử nó đang sử dụng mô-đun đầu vào evdev) sẽ xử lý chúng giống như bất kỳ sự kiện chuột nào khác.

Có thư viện có tên là libsuinput làm cho việc này khá dễ thực hiện. Nó thậm chí còn bao gồm example mouse input program mà bạn có thể sử dụng làm mô hình. Tuy nhiên, vì thiết bị của bạn là một thiết bị dựa trên cảm ứng, nó có thể sẽ sử dụng các trục tuyệt đối (ABS_X, ABS_Y) thay vì tương đối (REL_X, REL_Y).

+0

Tuyệt vời .. điều này chỉ có thể là câu trả lời. Tôi sẽ cần phải xem liệu thiết bị Linux nhúng của tôi có hỗ trợ hệ thống 'uinput' hay không. Cảm ơn bạn. – Chimera

9

Có một số phương pháp.

  1. Sử dụng XSendEvent. Lưu ý: một số khung ứng dụng bỏ qua các sự kiện được gửi với XSendEvent. Tôi nghĩ Gtk + không, nhưng tôi chưa kiểm tra.
  2. Sử dụng XTestFakeMotionEventXTestFakeButtonEvent. Bạn cần phần mở rộng XTest trên máy chủ X của bạn.
  3. Viết trình điều khiển hạt nhân cho thiết bị của bạn để nó sẽ xuất hiện dưới dạng chuột/bàn di chuột.
+0

Cảm ơn câu trả lời của bạn. – Chimera

6

Điều tuyệt vời nhất là triển khai trình điều khiển thiết bị bên trong hạt nhân tạo tệp /dev/input/eventX có giao thức evdev. Tôi khuyên bạn nên đọc cuốn sách có tên Linux Device Drivers nếu bạn muốn làm điều này. Cuốn sách có sẵn miễn phí trên web.

Nếu bạn muốn thực hiện việc này trong không gian người dùng, tôi khuyên bạn nên sử dụng Xlib (hoặc XCB). Trên đồng bằng Xlib (ngôn ngữ C), bạn có thể sử dụng X Test Extension hoặc XSendEvent().

Còn có một tệp nhị phân được gọi là xte từ gói xautomation (trên Debian, sudo apt-get install xautomation và sau đó là man xte). xte rất dễ sử dụng và bạn cũng có thể xem mã nguồn của nó để tìm hiểu cách sử dụng Tiện ích mở rộng thử nghiệm X.

Pointers:

+0

Cảm ơn bạn đã trả lời chi tiết. – Chimera

1

Có vẻ rằng afte r nghiên cứu thêm một chút, Gtk + sử dụng thư viện GDK có thể thực hiện những gì tôi muốn mà không cần phải nghiên cứu sâu về mã hóa X11 hoặc viết trình điều khiển Kernel. Mặc dù, nếu tôi có thời gian, tôi muốn viết trình điều khiển Chuột Kernel Linux.

Sử dụng GDK 2 Reference Manual tôi thấy tôi có thể làm như sau:

Sử dụng gtk_event_put() để nối thêm một GdkEvent loại GdkEventButton

Cấu trúc cho một GdkEventButton là:

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

Hầu hết các lĩnh vực sẽ là tầm thường để điền vào với ngoại lệ:

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. 

Tôi sẽ cần phải nghiên cứu cách chuyển đổi gốc màn hình phối tọa độ tương đối cửa sổ.

*device - Tôi không chắc liệu mình có cần sử dụng trường này (được đặt thành NULL) vì đây là thiết bị đầu vào mở rộng hay không. Tuy nhiên, nếu tôi cần có thiết bị hợp lệ ở đây tôi có thể sử dụng gdk_devices_list()

Các vấn đề liên quan