【问题标题】:How to capture the pointermotion event and limit the pointer in an area?如何捕获pointermotion事件并将指针限制在一个区域内?
【发布时间】:2017-03-07 08:51:05
【问题描述】:

我在 Ubuntu 16.10 的两台显示器上运行两个全屏应用程序。 app1 需要指针,而且必须始终保持焦点,所以我需要将指针锁定在 app1 中。

我写了一个这样的工具来抓取指针:

#include <stdio.h>
#include <X11/Xlib.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
Display *display;
XEvent xevent;
Window window;
int x,y;
void setPos(int x,int y){
  XWarpPointer(display,None,window,0,0,0,0,x,y);
  XFlush(display);
}
int main(int argc, char **argv){
  if( (display = XOpenDisplay(NULL)) == NULL )
    return -1;
  window = DefaultRootWindow(display);

  XAllowEvents(display, AsyncBoth, CurrentTime);
  XGrabPointer(display,window,0,PointerMotionMask,GrabModeAsync,GrabModeAsync,None,None,CurrentTime);
  while(1) {
    XNextEvent(display, &xevent);
    switch (xevent.type) {
        case MotionNotify:
          if(xevent.xmotion.x_root>1920){
             setPos(1920,xevent.xmotion.y_root);
          }
        break;
     }
  }
  return 0;
}

这个工具可以捕获指针的事件并限制指针停留在app1中,但是指针不能在app1中进行任何操作。除运动外的所有指针事件均无效。对代码有什么建议吗?或者有什么其他的想法来完成这项工作?

【问题讨论】:

  • 查看SendEvent() 将事件发回。您可能需要实际查找目标窗口。我对 X11 太生疏了,无法发布实际代码,但这应该是一个很好的线索。另外,请阅读该手册的索引,它有很好的章节标题(在本例中为“向其他应用程序发送事件”)。
  • 我用了这个方法,没用,什么都没变。 XSendEvent(display,PointerWindow,True,ButtonPressMask,&xevent);指针点击的窗口未激活,我运行该工具的终端一直处于活动状态。

标签: c linux pointers xlib xgrabpointer


【解决方案1】:

Xephyr 终于解决了这个问题。 使用此命令运行 Xephyr:

/usr/bin/Xephyr :1 -softCursor -name aaa -screen 1920x1080 -keybd   evdev,,device=/dev/input/eventkb,xkbrules=evdev,xkbmodel=evdev,xkblayout=us -mouse evdev,5,device=/dev/input/$eventmouse  -retro

Xephyr 将启动一个新的 Display 并抓住键盘和鼠标,然后您可以在 display :1 中运行您的应用。

顺便说一句: 1 重新插入设备时可能会更改键盘和鼠标的事件编号,因此请编写一个shell脚本来运行Xephey并在您的脚本中获取事件编号,如下所示:

eventkb=`grep -A5 "pci0000:00/0000:00:14.0/usb2/2-5/2-5:1.0/0003:1A81:1007" /proc/bus/input/devices | grep 'H: Handlers=' | grep --only-matching -e 'event[0-9]*'`

2 如果您不想以 root 运行 Xephyr,您将收到有关获取键盘和鼠标权限的错误。您可以创建文件 /etc/udev/rules.d/my.rules 并将SUBSYSTEM=="input", OWNER="username", GROUP="usernamer" 放入其中。然后你可以通过用户名运行 Xephyr。也许您需要重新登录或重新启动。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多