如何在X11窗口环境中监控剪贴板的内容变更?
X11剪贴板监听与格式获取方案
剪贴板全局变更监听实现
推荐优先使用XFixes扩展实现,无需抢占剪贴板所有权,不会干扰其他应用正常操作:
- 先调用
XFixesQueryExtension校验当前X Server是否支持XFixes扩展 - 为你的监听窗口调用
XFixesSelectSelectionInput(display, root_window, XA_CLIPBOARD, XFixesSetSelectionOwnerNotifyMask),注册CLIPBOARD选区的所有者变更事件监听 - 在事件循环中接收
XFixesSelectionNotify事件,收到该事件即代表剪贴板所有者变更,也就是有新内容被复制到剪贴板
如果环境不支持XFixes扩展,可使用原生X11接口实现:
- 创建一个无需显示的不可见窗口
- 调用
XSetSelectionOwner(display, XA_CLIPBOARD, your_window, CurrentTime)将自身设为CLIPBOARD选区所有者 - 监听
SelectionClear事件:收到该事件即代表其他客户端接管了剪贴板所有权,对应剪贴板内容变更 - 处理完本次变更后需要再次调用
XSetSelectionOwner重新获取所有权,才能监听下一次变更
注意:该方案需要额外实现选区请求转发逻辑,你持有所有权期间如果有其他客户端请求剪贴板内容,需要将请求转发给上一任所有者,否则会导致剪贴板内容失效。
枚举1~1000原子的可行性说明
完全不可行。X11原子分为预定义原子和动态创建原子两类:预定义原子数值确实在1~数百的区间,但绝大多数应用自定义的剪贴板格式(比如自定义MIME类型、应用私有格式)都是运行时动态生成的原子,数值普遍远大于1000,枚举该区间只能覆盖极少部分基础格式,完全无法满足全格式获取需求。
全格式获取的最优方案
按照ICCCM规范的标准实现,无需自行枚举原子:
当你需要获取当前剪贴板所有者支持的所有格式时,直接调用XConvertSelection(display, XA_CLIPBOARD, XA_TARGETS, your_property, your_window, CurrentTime),将转换目标指定为XA_TARGETS即可。
剪贴板所有者会在返回的SelectionNotify事件里,将所有支持的目标原子列表写入你指定的窗口属性中,你只需要解析该属性内容就能拿到全部可转换的格式原子,再调用XGetAtomName即可获取对应的格式名称,无遗漏覆盖所有支持的格式。
内容的提问来源于stack exchange,提问作者kishoredbn
相关产品推荐
相关产品推荐

