Rub*_*enC 5 c++ linux x11 clipboard codeblocks
你好我正在写一个c ++程序,我需要把剪贴板上的内容变成字符串变量.我找到了很多解决方案,但所有解决方案都是针对Windows编写的.有没有使用QT库的方法?我找到了与X11相关的东西,但不是很清楚.
非常感谢你
x11*_*ser 13
X11使用灵活的多缓冲区多格式异步应用程序端剪贴板协议.
大多数工具包都实现了它(GTK gtk_clipboard_get(),Qt QApplication::clipboard(),Tk的clipboard_get).但是你可以用X11 API做手工,例如,如果你不使用的工具包,或者如果你必须通过剪贴板缓冲区大量的数据,而不同时保持它所有在内存中.
可能有很多缓冲区,但您只需知道两个:
CLIPBOARD 是通常的显式缓冲区:使用"编辑/复制"菜单复制内容,然后使用"编辑/粘贴"菜单粘贴它.PRIMARY selection是一个隐式鼠标选择功能:当用鼠标光标选中时,文本会进入它,并在文本输入字段的中间点击时粘贴它.主要选择不需要按键,因此它可以在彼此相邻的窗口之间复制小片段.这个功能大多是特定于unix的,但我见过putty,trillian和一些gtk应用程序在Windows操作系统上模拟它.此外,当中间单击页面的空非交互空间时,firefox具有"粘贴并继续"功能.
为了优化那些应用程序端缓冲区:每次更改时,不是将整个剪贴板/选择推送到服务器,应用程序只是告诉服务器"我拥有它".要获取缓冲区,请让所有者向您提供其内容.这样,即使是大型缓冲区,在实际请求之前也不占用任何资源.
请求缓冲区时,请向所有者询问您需要的特定格式.例如,从seamonkey浏览器复制的图像(右键单击图像并按"复制图像")可以用不同的格式表示.如果将其粘贴到终端中,它将显示为图像URL.如果将其粘贴到libreoffice writer中,它将成为从该URL加载的图片.如果粘贴在gimp中,它就是图像本身.这是有效的,因为seamonkey是智能的,并为每个应用程序提供它要求的格式:终端的文本字符串,libreoffice的html和gimp的图像数据.要请求文本格式,您UTF8_STRING需要回退的格式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, e.g. 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;
}
Run Code Online (Sandbox Code Playgroud)
这适用于许多简单的情况.这里缺少的一件事是支持增量读取大缓冲区.我们加上吧!
某些应用可能需要复制/粘贴100千兆字节的文本日志.而X11允许这样!但是数据必须以递增方式传递,分成块.
如果请求的缓冲区太大,而不是将其存储到window属性中,则owner将设置format属性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, e.g. 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;
}
Run Code Online (Sandbox Code Playgroud)
例如,xsel工具使用INCR传输大于4000的缓冲区.根据ICCCM,由应用程序选择合理的大小限制.
相同的代码适用于PRIMARY选择.将"CLIPBOARD"替换为"PRIMARY"以打印PRIMARY选择内容.
XCopy()和XPaste()实现xsel和xclip来源您是否尝试先找到一个具有实现的程序,而不是代码?我为您做到了这一点,并发现了很多使用直接 X11 调用的实现。我认为最有价值的是这个,但你也可以读一下这个。只需找到任何程序并寻找来源即可。尝试在维基百科上查看哪些应用程序使用 x11 剪贴板/选择系统。
以下程序专门针对数据传输机制进行操作:
xcutsel将数据从选择传输到剪切缓冲区,反之亦然
xclipboard、glipper(Gnome)、parcellite(LXDE)和klipper(KDE)是剪贴板管理器,也许wmcliphist还可以xcb显示剪切缓冲区的内容并允许用户操作它们xselection,
xclip、xsel和xcopy是将数据复制到 X 选择或从 X 选择复制数据的命令行程序。xcopy 有一个详细选项,可以帮助调试 X 选择问题。Parcellite 还能够从命令行读取和写入特定的 X 选择。
synergy是一个跨平台工具,允许您在运行多个操作系统的多台计算机之间共享剪贴板
xfce4-clipman-plugin是一个“Xfce4 面板的剪贴板历史记录插件”,也是一个剪贴板管理器 xtranslate 在多语言词典中查找 Xselection 中的单词 autocutsel 同步剪切缓冲区和选择缓冲区
简而言之,理论上,X11 有 2 个“剪贴板”:实际上是键盘和用于选择的 - 您可以通过按鼠标中键立即将选择的文本粘贴到您想要的任何地方,而实际的“键盘”是用于主/默认剪贴板目的的不同种类的物品进行交换。
PS:根据我的经验,我不会再使用 x11 了。享受 :)