2013-06-28 101 views
9

這是一個後續How to insert synthetic mouse events into X11 input queue模擬按鈕點擊使用使用gtk_event_put和GdkEventButton結構

我試圖創建一個程序,它從外部設備輸入併產生鼠標點擊,使GTK+會得到GTK +並像處理鼠標點擊一樣正常處理事件。

我似乎可以用一個GdkEventButton結構: https://developer.gnome.org/gdk/stable/gdk-Event-Structures.html#GdkEventButton

但我不知道如何確定的值,爲每個字段輸入。我正在尋找來自某人使用gtk_event_put()GdkEventButton結構的示例代碼或建議的小片段。

編輯:如果有人知道與我的回答不同或更好的方式,請讓我知道。

回答

4

經過一番研究後,我得知GTK+/GDK 2.14及更新版本有一些功能可以爲GTK+應用程序創建自動化測試套件。

我能夠使用gdk_test_simulate_button來模擬鼠標點擊。這可能不是最佳的解決方案,但現在它似乎運作良好。

+0

鏈接已死亡。在2014年9月12日我發現了一個文檔在這裏:https://developer.gnome.org/gdk3/stable/gdk3-Testing.html#gdk-test-simulate-button通過谷歌搜索注意gdk_test_simulate_button 也有一些所謂的gtk_test_widget_click ()我在這裏找到一個簡短的文檔:https://people.gnome.org/~shaunm/girdoc/C/Gtk.test_widget_click.html – msouth

6

還有另外一種方法,但是我要用這種方式來呈現,包括使用純X11,雖然看到你的問題的標籤,但使用X11的答案也是可以接受的。這就是說,讓我先介紹一下所有事情發生的功能,其中一件事,我會稍微詳細一些,以防其他人不明白如何使用這個功能。


void 
mouse_click(Display *display, int x, int y, int click_type, struct timeval *t); 
  • 顯示結構以前XOpenDisplay()包含所有有關X服務器返回的信息。
  • x指針相對於屏幕根部的x座標。
  • y指針相對於屏幕根目錄的y座標。
  • click_type點擊的類型。對於此答案,MOUSE_RIGHT_CLICKMOUSE_LEFT_CLICK
  • ttimeval結構,指定點擊應該保持按下的時間間隔。

實施

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <time.h> 
#include <sys/types.h> 
#include <sys/select.h> 
#include <X11/Xlib.h> 
#include <X11/Xutil.h> 

#define portable_usleep(t) select(0, NULL, NULL,NULL, t) 

enum { MOUSE_RIGHT_CLICK, MOUSE_LEFT_CLICK }; 

void 
mouse_click(Display *display, int x, int y, int click_type, struct timeval *t) 
{ 
     Window root; 
     XEvent event; 

     root = DefaultRootWindow(display); 
     XWarpPointer(display, None, root, 0, 0, 0, 0, x, y); 

     memset(&event, 0, sizeof(event)); 

     event.xbutton.type  = ButtonPress; 
     event.xbutton.button  = click_type; 
     event.xbutton.same_screen = True; 

     XQueryPointer(display, root, &event.xbutton.root, &event.xbutton.window, 
        &event.xbutton.x_root, &event.xbutton.y_root, 
        &event.xbutton.x, &event.xbutton.y, &event.xbutton.state); 

     event.xbutton.subwindow = event.xbutton.window; 

     while(event.xbutton.subwindow) { 
       event.xbutton.window = event.xbutton.subwindow; 
       XQueryPointer(display, event.xbutton.window,&event.xbutton.root, 
       &event.xbutton.subwindow, &event.xbutton.x_root, 
       &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, 
       &event.xbutton.state); 
     } 

     if(XSendEvent(display, PointerWindow, True, 0xfff, &event)==0) 
       fprintf(stderr, "XSendEvent()\n"); 

     XFlush(display); 
     portable_usleep(t); /* keeps the click pressed */ 

     event.type = ButtonRelease; 
     event.xbutton.state = 0x100; 

     if(XSendEvent(display, PointerWindow, True, 0xfff, &event)==0) 
       fprintf(stderr, "XSendEvent()\n"); 

     XFlush(display); 
} 

嗯,這個功能是相當直接的,例如,在按下一半的第二位置500645按鈕左邊點擊,這是多麼:

int 
main(void) 
{ 
     int x; 
     int y; 
     Display  *display; 
     struct timeval t; 

     display = XOpenDisplay(NULL); 

     if(!display) { 
       fprintf(stderr, "Can't open display!\n"); 
       exit(EXIT_FAILURE); 
     } 

     x = 500; 
     y = 645; 

     t.tv_sec = 0; 
     t.tv_usec = 500000; /* 0.5 secs */ 

     mouse_click(display, x, y, MOUSE_LEFT_CLICK, &t); 

     XCloseDisplay(display); 
     return 0; 
} 

編譯

$ gcc -o click click.c -lX11 
+0

感謝您的答案。我不確定我可以在GTK +/GDK環境中做到這一點。我將對XSendEvent()進行一些調查,看看我能否讓GDK提供所需的顯示和窗口參數。 – Chimera

+0

謝謝基拉。鼠標左鍵工作。但鼠標右鍵不起作用。你對如何解決這個問題有任何想法嗎? :) –

+0

@JuanCarlosKuriPinto對不起,我的意思是儘快回覆你,只要閱讀你的評論,不幸的是我還沒有能夠在我的Mac上測試這個代碼...我想我需要一個X11包:\反正,作爲一旦我從假期回家,我會檢查它。 – yeyo