使用gtk_event_put和GdkEventButton结构使用GTK +模拟按钮单击

时间:2013-06-28 19:54:44

标签: c gtk x11

这是How to insert synthetic mouse events into X11 input queue

的后续行动

我正在尝试创建一个程序,该程序从外部设备获取输入并生成鼠标单击,以便GTK+获取并处理事件,就像鼠标点击正常发生一样。

似乎我可以使用GdkEventButton结构: https://developer.gnome.org/gdk/stable/gdk-Event-Structures.html#GdkEventButton

但我不确定如何确定每个字段输入的值。我正在寻找一小段示例代码或来自使用gtk_event_put()结构GdkEventButton的人的建议。

编辑:如果有人知道的方式与我的答案不同或更好,请告诉我。

2 个答案:

答案 0 :(得分: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
  • t timeval结构,指定了点击应保持按下的时间间隔。

<强>实施

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

嗯,这个功能很直接,例如,左键点击位置500,645按钮按下半秒钟,这就是:

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

答案 1 :(得分:4)

经过一些研究后,我得知GTK+/GDK 2.14和更新版本有一些功能可以为GTK+应用程序创建自动化测试套件。

我可以使用gdk_test_simulate_button来模拟鼠标点击。 可能不是最佳解决方案,但现在它似乎运作良好。