在Android上使用/ dev / uinput时单击错误的位置

时间:2014-11-28 10:57:02

标签: android

我的项目功能看起来像VNC。但与此略有不同。 我有一个在Android上运行的服务器程序和一个在PC上运行的客户端。我想通过在PC上操作来控制手机。

这个项目的大部分内容已经完成,但在控制步骤中发生了一点错误。也许你知道我们永远 使用the user level input subsystem来实现响应操作命令的目标 来自PC客户端。在编写这部分程序时,我引用了其他人。另外,我是Android新手,所以有些事情是我无法控制的。

好的,我会详细说明如下。 例如,当您单击鼠标或按下PC上的某些键时,服务器会通过某些协议接收此命令,例如 RFB,并获取有关您的命令事件的相关信息,例如按钮面具(可以决定左或 单击鼠标右键)或位置(X,Y坐标)。按照向Android发送命令的三个步骤。

首先,通过" / dev / uinput"的开放设备创建输入设备。在android中。 其次,将相关事件注入输入子系统。 然后,将事件写入虚拟输入子系统。

简化代码:

//First ADN SECOND STEPS:
    int initial()
    {
        int inputfd = -1;

        uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);

        /* Set device to handle following types of events: */

      /* Key and button repetition events */
        if (ioctl(uinput_fd, UI_SET_EVBIT, EV_REP) == -1)
            return -1;

        /* Absolute pointer motions */
        if (ioctl(uinput_fd, UI_SET_EVBIT, EV_ABS) == -1)
            return -1;
        /* Configure device to handle absolute x and y axis. */
        if (ioctl(uinput_fd, UI_SET_ABSBIT, ABS_X) == -1)
            goto err;
        if (ioctl(uinput_fd, UI_SET_ABSBIT, ABS_Y) == -1)
            return -1;

        /* Synchronization events, this is probably set implicitely too. */
        if (ioctl(uinput_fd, UI_SET_EVBIT, EV_SYN) == -1)
            return -1;


        struct uinput_user_dev user_dev;
        /* Set device-specific information. */
        memset(&user_dev, 0, sizeof(user_dev));
        strncpy(user_dev.name, device_name, UINPUT_MAX_NAME_SIZE);
        user_dev.id.bustype = BUS_USB;
        user_dev.id.vendor = 1;
        user_dev.id.product = 1;
        user_dev.id.version = 1;

        //minor tweak to support ABSolute events
        user_dev.absmin[ABS_X] = 0;
        user_dev.absmax[ABS_X] = 799;
        user_dev.absfuzz[ABS_X] = 0;
        user_dev.absflat[ABS_X] = 0;

        user_dev.absmin[ABS_Y] = 0;
        user_dev.absmax[ABS_Y] = 479;
        user_dev.absfuzz[ABS_Y] = 0;
        user_dev.absflat[ABS_Y] = 0;

        if (write(uinput_fd, &user_dev, sizeof(user_dev)) != sizeof(user_dev))
            return -1;

        if (ioctl(uinput_fd, UI_DEV_CREATE) == -1)
            return -1;
    }

//THREE STEP:
    //call by ptrEvent
    int suinput_write(int uinput_fd, uint16_t type, uint16_t code, int32_t value)
    {
        struct input_event event, nullevent;
        memset(&event, 0, sizeof(event));
        gettimeofday(&event.time, 0); /* This should not be able to fail ever.. */
        event.type = type;
        event.code = code;
        event.value = value;
        if (write(uinput_fd, &event, sizeof(event)) != sizeof(event))
            return -1;

        return 0;
    }
    //begin to deal with event
    void ptrEvent(int buttonMask, int x, int y, rfbClientPtr cl)
    {

        static int leftClicked=0;

        if ( inputfd == -1 )
            return;

        if (buttonMask & 1)
        { //left btn clicked
            leftClicked=1;

            suinput_write(inputfd, EV_ABS, ABS_X, x);
            suinput_write(inputfd, EV_ABS, ABS_Y, y);
            suinput_write(inputfd,EV_KEY,BTN_TOUCH,1);
            suinput_write(inputfd, EV_SYN, SYN_REPORT, 0);
        }
        else if (leftClicked)
        { //left btn released
            leftClicked=0;
            suinput_write(inputfd, EV_ABS, ABS_X, x);
            suinput_write(inputfd, EV_ABS, ABS_Y, y);
            suinput_write(inputfd,EV_KEY,BTN_TOUCH,0);
            suinput_write(inputfd, EV_SYN, SYN_REPORT, 0);
        }
    }

Android设备的分辨率为800 * 480。和客户端图片也有相同的大小。我调试上面的代码并找到它 服务器从事件消息中接收正确的位置。在ptrEvent的功能中,X和Y对应于真实 点击位置发生在PC上。但是从Android上显示的实际按压位置来看,还有不同之处。正如你看到的, 我将Android虚拟输入设备的最大绝对范围设置为与实际分辨率相同,因此显然客户端和服务器之间没有偏差 坐标。为什么会这样?

0 个答案:

没有答案