简介

几乎所有的Linux发行版都使用X11实现剪贴板功能

剪贴板的说法可能是从Windows传入的, 在X11中剪贴板就叫做selection, 并且系统中可以有任意多个selection

如无特别说明, 下文的剪贴板和selection是相同的意思

复制和粘贴

从用户的直观感受来说, 基本的剪贴板操作有2个: 复制和粘贴

复制, 就是把数据放到剪贴板
粘贴, 就是把数据从剪贴板取出来

但是, 在X11中的实现却不是这样
X11复制时, 数据并没有拷贝到剪贴板, 数据是在粘贴时, 直接发送给粘贴的窗口

听起来有点抽象, 举个栗子
用户在窗口A选中了一段文字, 点击复制
然后在窗口B点击粘贴

X11剪贴板

X11的实现流程是这的

  1. 窗口A所属的程序使用XSetSelectionOwner()获取剪贴板的所有权, 此时没有任何数据操作, 仅仅声明现在自己拥有剪贴板
  2. 窗口A所属的程序等待剪贴板的粘贴请求
  3. 用户在窗口B点击粘贴
  4. 窗口B所属的程序使用XConvertSelection()告诉XServer说我要粘贴, 请把数据发到我的窗口属性上
  5. XServer向窗口A发送粘贴请求, 告诉A把数据设置到窗口B的属性上
  6. 窗口A使用XChangeProperty()把数据设置到窗口B的属性上
  7. 窗口B收到剪贴板数据设置完成的通知, 使用XGetWindowProperty()把数据取出来

以上是大概的流程, 可以看到还是相当麻烦的

这是因为X协议是C/S架构
X客户端只能和XServer通信(可以把窗口A当做一个客户端, B当做另一个客户端)
窗口A要把剪贴板数据发给B只能通过XServer中转

以上流程使用libX11实现的关键代码如下

窗口A

sel = XInternAtom(dpy, "CLIPBOARD", False);
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
// 窗口A拥有剪贴板
XSetSelectionOwner(dpy, sel, A, CurrentTime);
for (;;)
{
// 等待其他X客户端发出获取剪贴板数据的请求
XNextEvent(dpy, &ev);
switch (ev.type)
{case SelectionRequest:sev = (XSelectionRequestEvent*)&ev.xselectionrequest;// 把剪贴板数据设置到想要粘贴的x客户端窗口的属性上XChangeProperty(dpy, sev->requestor, sev->property, utf8, 8, PropModeReplace,(unsigned char *)now, strlen(now));// 发送SelectionNotify事件给请求剪贴板的x客户端XSendEvent(dpy, sev->requestor, True, NoEventMask, (XEvent *)&ssev);
}

窗口B

sel = XInternAtom(dpy, "CLIPBOARD", False);
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
// 告诉窗口A, 把剪贴板数据转换成指定的格式,
// 并把数据放到窗口B的的属性上
// 此后窗口A会收到SelectionRequest事件
XConvertSelection(dpy, sel, utf8, property, B, CurrentTime);
// 等待窗口A把数据设置完成
XNextEvent(dpy, &ev);
switch (ev.type)
{// 剪贴板数据已经放到指定的窗口, 可以获取了case SelectionNotify:XGetWindowProperty();
}

数据类型

  • 剪贴板的数据类型叫做target, 例如UTF8_STRING, TEXT等
  • 有一个特殊的剪贴板类型叫做TARGETS, 通过它可以获取剪贴板数据支持转换成的格式

异常情况

理论上来讲
2个X客户端之间传输剪贴板数据, 只能通过XServer实现
XServer不保存剪贴板数据, 只转发selection事件
数据直接由2个X客户端通过设置窗口属性传递(当然这也要通过XServer中转)

那么就会出现一个问题
如果一个x客户端复制了一个内容, 然后这个x客户端关闭了
这时另一个程序想粘贴数据是不可能的

但是实际测试并不是这样
在Ubuntu上测试时发现, 复制内容的那个程序(窗口A)关闭了,
其他程序(窗口B)还是可以粘贴

难道以上的理论错了
当然不是
只是情况更加复杂了
因为又多了一个Clipboard manager

Clipboard manager的大概工作流程如下

  1. Clipboard manager获取剪贴板的所有权
  2. 如果其他程序要复制数据, 会获取剪贴板所有权, 这时Clipboard manager失去所有权, 它会这么做
    • 获取当前剪贴板的数据
    • 自己提供数据
    • 再次获取剪贴板所有权

所以当A关闭后, B粘贴的数据实际上是Clipboard manager提供的

参考资料

X11: How does “the” clipboard work?

Linux中的剪贴板--X11和selection相关推荐

  1. linux vim 粘贴 没有保持原来的格式,linux中的剪贴板用法,实现vim中原格式粘贴...

    不同于Windows,Linux系统里存在两个剪切板:一个叫做选择缓冲区(X11 selection buffer),另一个才是剪切板(clipboard). 选择缓冲区是实时的,当使用鼠标或键盘选择 ...

  2. macOS 使用 X11 运行远端 linux 中的 x11 client 图形程序

    安装 brew install --cask xquartz 配置 打开 xquartz,新建一个终端,然后执行 xhost + 开放权限. linux 中 sshd 配置 /etc/ssh/sshd ...

  3. linux五文件类型,Linux中常见的文件类型

    1>系统文件 文件扩展名    说明 .conf    一种配置文件.配置文件有时也使用 .cfg .lock    锁(lock)文件:用来判定程序或设备是否正在被使用 .rpm     Re ...

  4. linux 找到安装的软件包,如何在 Linux 中列出可用的软件包组

    原标题:如何在 Linux 中列出可用的软件包组 编译自: https://www.2daygeek.com/how-to-list-an-available-package-groups-in-li ...

  5. linux 中如何将文件粘贴到usr下的lib内,学会在Linux下GCC生成和使用静态库和动态库...

    一.基本概念1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主 ...

  6. Linux中的目录和文件管理

    Linux中的目录和文件管理 1:Linux的命令分类:内部命令和外部命令 内部命令属于shell解释器的一部分 外部命令是独立于shell解释器之外的程序文件 2:Linux命令的通用格式 命令字  ...

  7. linux 图形界面 x x11 gnome xorg kde 之间的关系

    LINUX初学者经常分不清楚linux和X之间,X和Xfree86之间,X和KDE,GNOME等之间是什么关系.常常混淆概念,本文以比较易于理解的方式来解释X,X11,XFREE,WM,KDE,GNO ...

  8. Linux中使用gcp拷贝报错:dbus.exceptions.DBusException: org.freedesktop.DBus.Error.NotSupported:

    1 在linux中使用gcp拷贝的时候报错 Linux中使用gcp拷贝报错:dbus.exceptions.DBusException: org.freedesktop.DBus.Error.NotS ...

  9. Linux中关于useradd、chmod、chown、getfacl、setfact等权限设置

    Linux中关于useradd.chmod.chown.getfacl.setfact等权限设置 文章目录: 一.Linux用户管理 1.用户(user).用户组(group).其他用户概念(othe ...

最新文章

  1. python字典练习题
  2. PowerShell因为在此系统中禁止执行脚本
  3. python set union_python – set.union()抱怨它在传入生成器时没有参数
  4. 【H264/AVC 句法和语义详解】(五):Exp-Golomb指数哥伦布编码(理论篇)
  5. OSS 上传出现异常
  6. oracle 审计结果表,oracle对某表进行审计,观察对这个表的增删改查等sql操作
  7. C++11多线程 unique_lock详解
  8. 济南大学Oj系统c语言,“浪潮杯”第十届山东省大学生ACM程序设计竞赛在济南大学举行...
  9. 利用python进行正球面的大圆航程与横向线航程计算
  10. 衰老,其实是一种疾病?
  11. EMV log 解析
  12. [ScyllaHide] 02 InjectorCLI源码分析
  13. wince模拟器上网_wince5.0模拟器下载
  14. git合并多次提交为一次提交
  15. C++ 之 for 循环 | C++11 for 循环 | 内存 Destory 示例
  16. P4043 [AHOI2014/JSOI2014]支线剧情(有源汇上下界最小费用可行流)
  17. 多个日期时间段进行合并计算时长,剔除重叠时间段
  18. 每股收益再创新高,增长速度趋于减缓:上市公司半年报业绩波澜不惊
  19. Android漂浮碰壁动画
  20. Vijos1234 口袋的天空 题解

热门文章

  1. 云表MES系统助力小型企业
  2. 群辉docker阿里云ipv6域名解析
  3. 对于电影《八佰》,知乎与豆瓣的评价相差巨大?分析下电影评论
  4. ​手机微信可以批量删除好友了!(文末送书)
  5. double类型问题(精度丢失和自动拆箱)
  6. 22届应届生入职华为OD一个半月,治好了我的精神内耗...
  7. C语言复习笔记——适合一些需要复习和进阶c语言的朋友,这只能说是个概要。当然,如果朋友你看到某个内容能联想到知识点,那你应该是掌握了的,你可以尝试找找其他的文章去深入理解下,如有错误和疑问可以直接指出
  8. ios 滤镜处理(详细滤镜介绍)及处理方法
  9. 达观AI+知识图谱技术在数字档案馆建设中的探索
  10. Python3基础,这篇就够了(总结版)