你好我正在写一个c + +程序,我需要得到剪贴板上的东西到一个stringvariables。 我发现了很多解决scheme,但都是为Windows编写的。 有没有使用QT库的方法? 我发现了一些与X11相关的东西,但不是很明确。
非常感谢你
你有没有试图找到一个代码,而是一个具有实现的程序? 我为你做了,发现了很多使用直接X11调用的实现。 我觉得最有价值的是这个,但是你也可以阅读这个 。 只要找到任何程序,并寻找来源。 尝试在维基百科看什么应用程序使用x11剪贴板/选择系统。
以下程序专门用于数据传输机制:
xcutsel
将选择的数据传输到缓冲区,反之亦然
xclipboard
,xclipboard
(Gnome),parcellite
(LXDE)和klipper
(KDE)是剪贴板管理器,也许wmcliphist
以及xcb
显示剪切缓冲区的内容,并允许用户操纵它们xselection,
xclip
,xsel
和xcopy
是命令行程序,将数据复制到X选择或从X选择复制数据。 xcopy有一个详细的选项,可以帮助调试X选择问题。 parcellite也能够从命令行读取和写入特定的X选项。
synergy
是一个跨平台的工具,它允许你在运行多个操作系统的多台计算机上共享剪贴板
xfce4-clipman-plugin
是一个“xfce4-clipman-plugin
面板的剪贴板历史记录插件”,也是一个剪贴板管理器xtranslate在多语言字典中的Xselection中查找单词autocutsel syncs剪切缓冲区和选择缓冲区
简而言之,理论上,X11有2个“剪贴板”:实际上是一个键盘和选择 – 你选择的文本可以粘贴到你想要的任何地方,通过按鼠标中键,而实际的“键盘”是为主/默认剪贴板的目的交换不同种类的物体。
PS我经验之后不再使用x11。 请享用 :)
X11使用灵活的多缓冲多格式异步应用程序端剪贴板协议。
大多数工具包都已经实现了(GTK的gtk_clipboard_get()
,Qt的QApplication::clipboard()
,Tk的clipboard_get )。 但是,您可以使用X11 API手动执行此操作,例如,如果您不使用工具包,或者必须通过剪贴板缓冲区传递大量数据,而不将其全部保存在内存中。
可能有很多缓冲区,但你只需要知道两个:
CLIPBOARD
是通常的显式缓冲区:在“编辑/复制”菜单中复制其中的内容,然后使用“编辑/粘贴”菜单进行粘贴。 PRIMARY
选择是一个隐含的鼠标选择功能:当用鼠标光标选中时,文本进入,在文本输入框中点击鼠标中键。 主要选择不需要按键,因此在彼此相邻的窗口之间复制小型碎片很有用。 这个功能大多是特定于unix的,但是我已经看到putty,trillian和一些gtk应用程序在Windows操作系统上模拟它。 当中间点击页面的空白非交互式空间时,Firefox也有“粘贴并继续”功能。
为了优化这些应用程序缓冲区,应用程序只是告诉服务器“我拥有它”,而不是每次改变整个剪贴板/选择到服务器。 为了获得缓冲区,你要求所有者给你的内容。 这样,即使是一个大型的缓冲区,在实际请求之前也不需要资源
当请求缓冲区时,您要求所有者提供您需要的特定格式。 例如,从seamonkey浏览器复制的图像(右键单击图像并按“复制图像”)可以用不同的格式表示。 如果您将其粘贴到终端中,它将显示为图片网址。 如果将它粘贴到libreoffice writer中,它将成为从该URL加载的图片。 如果以瘸子的形式粘贴的话就是图像本身。 这是因为seamonkey是聪明的,并为每个应用程序提供格式要求:终端的文本字符串,libreoffice的html和gimp的图像数据。 要请求文本格式,请求回UTF8_STRING
STRING
UTF8_STRING
格式。
当您要求另一个应用程序准备缓冲区时,这可能需要一些时间,请求是异步的 :所有者准备缓冲区,将其保存在指定的位置(窗口属性用作临时存储),并通过SelectionNotify
事件通知您当它完成。
所以得到缓冲区:
CLIPBOARD
, PRIMARY
),格式( UTF8_STRING
, STRING
)和窗口属性来存储结果到 XConvertSelection()
来请求缓冲区 SelectionNotify
事件 // gcc -o xclipget xclipget.c -lX11 #include <stdio.h> #include <limits.h> #include <X11/Xlib.h> Bool PrintSelection(Display *display, Window window, const char *bufname, const char *fmtname) { char *result; unsigned long ressize, restail; int resbits; Atom bufid = XInternAtom(display, bufname, False), fmtid = XInternAtom(display, fmtname, False), propid = XInternAtom(display, "XSEL_DATA", False), incrid = XInternAtom(display, "INCR", False); XEvent event; XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime); do { XNextEvent(display, &event); } while (event.type != SelectionNotify || event.xselection.selection != bufid); if (event.xselection.property) { XGetWindowProperty(display, window, propid, 0, LONG_MAX/4, False, AnyPropertyType, &fmtid, &resbits, &ressize, &restail, (unsigned char**)&result); if (fmtid == incrid) printf("Buffer is too large and INCR reading is not implemented yet.\n"); else printf("%.*s", (int)ressize, result); XFree(result); return True; } else // request failed, eg owner can't convert to the target format return False; } int main() { Display *display = XOpenDisplay(NULL); unsigned long color = BlackPixel(display, DefaultScreen(display)); Window window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0,0, 1,1, 0, color, color); Bool result = PrintSelection(display, window, "CLIPBOARD", "UTF8_STRING") || PrintSelection(display, window, "CLIPBOARD", "STRING"); XDestroyWindow(display, window); XCloseDisplay(display); return !result; }
这将适用于很多简单的情况。 这里缺少的一件事是支持增量读取大缓冲区。 让我们来添加它!
有些应用程序可能需要复制/粘贴100千兆字节的文本日志。 而X11允许的! 但数据必须逐步传递,分成块。
如果所请求的缓冲区太大,而不是将其存储到窗口属性中,则所有者将设置INCR
格式的属性。 如果你删除它,所有者就会假设你已经读过它,并把下一个块放在同一个属性中。 直到最后一个块被读取和删除。 最后,owner将大小为0的属性标记为数据的结尾。
因此,要读取较大的缓冲区,请删除INCR
属性,然后等待该属性再次出现( PropertyNotify
事件,状态== PropertyNewValue
),读取并删除它,等待它再次出现,依此类推,直到出现零大小。
// gcc -o xclipget xclipget.c -lX11 #include <stdio.h> #include <limits.h> #include <X11/Xlib.h> Bool PrintSelection(Display *display, Window window, const char *bufname, const char *fmtname) { char *result; unsigned long ressize, restail; int resbits; Atom bufid = XInternAtom(display, bufname, False), fmtid = XInternAtom(display, fmtname, False), propid = XInternAtom(display, "XSEL_DATA", False), incrid = XInternAtom(display, "INCR", False); XEvent event; XSelectInput (display, window, PropertyChangeMask); XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime); do { XNextEvent(display, &event); } while (event.type != SelectionNotify || event.xselection.selection != bufid); if (event.xselection.property) { XGetWindowProperty(display, window, propid, 0, LONG_MAX/4, True, AnyPropertyType, &fmtid, &resbits, &ressize, &restail, (unsigned char**)&result); if (fmtid != incrid) printf("%.*s", (int)ressize, result); XFree(result); if (fmtid == incrid) do { do { XNextEvent(display, &event); } while (event.type != PropertyNotify || event.xproperty.atom != propid || event.xproperty.state != PropertyNewValue); XGetWindowProperty(display, window, propid, 0, LONG_MAX/4, True, AnyPropertyType, &fmtid, &resbits, &ressize, &restail, (unsigned char**)&result); printf("%.*s", (int)ressize, result); XFree(result); } while (ressize > 0); return True; } else // request failed, eg owner can't convert to the target format return False; } int main() { Display *display = XOpenDisplay(NULL); unsigned long color = BlackPixel(display, DefaultScreen(display)); Window window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0,0, 1,1, 0, color, color); Bool result = PrintSelection(display, window, "CLIPBOARD", "UTF8_STRING") || PrintSelection(display, window, "CLIPBOARD", "STRING"); XDestroyWindow(display, window); XCloseDisplay(display); return !result; }
例如, xsel
工具对大于4000的缓冲区使用INCR
传输。根据ICCCM,选择合理的大小限制取决于应用程序。
相同的代码适用于PRIMARY
选择。 将“CLIPBOARD”替换为“PRIMARY”以打印PRIMARY
选择内容。
XCopy()
和XPaste()
实现 xsel
和xclip
来源