0

抱歉标题很差,要更好地描述它并不容易。我正在学习 C,作为一个玩具项目,我正在为我的窗口管理器构建一个简单的状态栏。基本上它只是将文本输出到根 X11 窗口名称,由 wm (DWM) 获取。

现在我想添加检测到的简单点击,以便在点击特定区域时可以做一些事情。鼠标的轮询发生在一个while循环中;状态栏的更新也存在于 while 循环中,但间隔不同(频率较低)。一切正常,除了没有其他 X11 应用程序接收到我在 while 循环中听到的鼠标点击。

XNextEvent首先使用,但发现如果鼠标空闲,它会阻塞 while 循环。然后我了解XCheckWindowEvent了如果我要轮询的事件匹配,哪个返回布尔值,然后我可以处理它。但是当鼠标空闲时(大部分时间),循环不会暂停。

但是,既然这样做了,每当我移动鼠标时,我就不能再点击任何其他窗口了。光标移动得很好,但点击似乎不起作用。

我说得有道理吗?

这是我的程序列表(对于状态设置部分稍微简化,因为这可能会分散注意力)。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <wchar.h>
#include <unistd.h>
#include <fcntl.h>
#include <X11/Xlib.h>

#define EVTMASK (ButtonPressMask | PointerMotionMask)

void set_status(Display *display, Window window, char *str);
void process_mouse(Display *display, Window window, XEvent xevent);

char *key_name[] = {
    "first",
    "second (or middle)",
    "third"
};

int 
main(void) 
{
  const int MSIZE = 1024;
  Display *display;
  XEvent xevent;
  Window window;
  char *status;
  char *bg_color    = "#000000";
  char *clr_yellow  = "#ecbe7b";
  time_t previousTime = time(NULL);
  time_t interval_status = 1;
  time_t currentTime;

  if (!(display = XOpenDisplay(NULL))) {
    fprintf(stderr, "Cannot open display.\n");
    return EXIT_FAILURE;
  }

  // Setup X11 for mouse grabbing
  window = DefaultRootWindow(display);
  XAllowEvents(display, AsyncBoth, CurrentTime);

  XGrabPointer(display, 
      window,
      1, 
      PointerMotionMask | ButtonPressMask | ButtonReleaseMask , 
      GrabModeAsync,
      GrabModeAsync, 
      None,
      None,
      CurrentTime);

  status = (char*) malloc(sizeof(char)*MSIZE);
  if(!status)
    return EXIT_FAILURE;

  while(1)
  { 
    process_mouse(display, window, xevent);
    if((time(&currentTime) - previousTime) >= interval_status)
    {
      int ret = snprintf(status, MSIZE, "^b%s^^c%s^%s Status me!", bg_color, clr_yellow);
      set_status(display, window, status);
      previousTime += interval_status;
    }
  }

  return 0;
}

void 
set_status(Display *display, Window window, char *str) 
{
  XStoreName(display, window, str);
  XSync(display, False);
}

void
process_mouse(Display *display, Window window, XEvent xevent)
{
  if(XCheckWindowEvent(display, window, EVTMASK, &xevent)) {
    switch (xevent.type) {
      case MotionNotify:
        printf("Mouse move      : [%d, %d]\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
        break;
      case ButtonPress:
        printf("Button pressed  : %s\n", key_name[xevent.xbutton.button - 1]);
        break;
      case ButtonRelease:
        printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]);
        break;
    }
    XPutBackEvent(display, &xevent);
  }
}

开放式问题:我应该回到NextEvent方法并在不同的线程上听鼠标吗?

4

0 回答 0