X11等待并获取剪贴板文本

22

我需要监控X11剪贴板。

目前,我每隔5秒请求一次剪贴板选择,然后对从剪贴板返回的文本进行哈希,将其与上次检查时计算出的哈希进行比较。如果哈希值不同,我会分析文本内容并执行一些操作...

我不喜欢我的方法。我来自Windows,在winapi中,内核会在剪贴板发生变化时通知你的程序,这样更有效率!

我只想知道是否可能像winapi一样,当剪贴板发生变化时,X11可以通知程序?使用X11检查剪贴板修改的最有效方法是什么?

3个回答

15

使用 Xfixes 扩展中的 XFixesSelectSelectionInput() 函数,并等待 XFixesSelectionNotify 事件。

示例:

// gcc -o xclipwatch xclipwatch.c -lX11 -lXfixes
...
#include <X11/extensions/Xfixes.h>
...
void WatchSelection(Display *display, Window window, const char *bufname)
{
  int event_base, error_base;
  XEvent event;
  Atom bufid = XInternAtom(display, bufname, False);

  assert( XFixesQueryExtension(display, &event_base, &error_base) );
  XFixesSelectSelectionInput(display, DefaultRootWindow(display), bufid, XFixesSetSelectionOwnerNotifyMask);

  while (True)
  {
    XNextEvent(display, &event);

    if (event.type == event_base + XFixesSelectionNotify &&
        ((XFixesSelectionNotifyEvent*)&event)->selection == bufid)
    {
      if (!PrintSelection(display, window, bufname, "UTF8_STRING"))
        PrintSelection(display, window, bufname, "STRING");

      fflush(stdout);
    }
  }
}
...

这对于 bufname == "CLIPBOARD"bufname == "PRIMARY" 选择都适用。

还请查看 此答案 中的 PrintSelection() 函数。


2
请不要将强制命令放入assert()中,因为assert()会让人误以为它可以被省略(参见NDEBUG)。更好的方法是:int xfixinstalled = XFixesQueryExtension(display,&event_base,&error_base); assert(xfixinstalled); - Tino
我在我的Ubuntu 20.04中似乎缺少X11/extensions/xfixes.h - 你有任何想法在哪里可以找到它吗?这是必须安装的东西吗?我只看到了xfixesproto.h。 - tofutim
@tofutim 我用命令 apt-file search Xfixes.h 进行了搜索。它告诉我需要安装 libxfixes-dev,所以我安装了它,然后一切正常运行。 - undefined

1
  1. 使用 GetSelectionOwner 查找具有选择的窗口(PRIMARY 和 CLIPBOARD)
  2. 通过发送 SelectionRequest 获取选择的副本,通知您的应用程序
  3. 监听 SelectionClear 事件
  4. 使用来自 SelectionClear 事件的 ID 更新具有选择的窗口,转到步骤 2

当选择所有者被关闭时,您该怎么做? - retroj

1

x11user的被接受答案很不错。但是你可能想要一个非阻塞的while循环,所以你可以采用那个答案,并像这样进行调整。

// get the internal X11 event file descriptor
int x11fd = ConnectionNumber(display);

while(!shutdown)
{
  if(!XPending(display)) {
    // wait on the file descriptor
    // you can use poll, epoll, select, eventfd, etc.
  }

  XNextEvent(display, &event);
  // process the event
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接