如何用X11复制到剪贴板?

使用OS X上的框架,我可以使用以下方法将PNG复制到粘贴(在C中 – 显然我可以使用Cocoa的NSPasteboard):

#include <ApplicationServices/ApplicationServices.h> int copyThatThing(void) { PasteboardRef clipboard; if (PasteboardCreate(kPasteboardClipboard, &clipboard) != noErr) { return -1; } if (PasteboardClear(clipboard) != noErr) { CFRelease(clipboard); return -1; } size_t len; char *pngbuf = createMyPNGBuffer(&len); /* Defined somewhere else */ if (pngbuf == NULL) { CFRelease(clipboard); return -1; } CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, pngbuf, len, kCFAllocatorNull); if (data == NULL) { CFRelease(clipboard); free(pngbuf); return -1; } OSStatus err; err = PasteboardPutItemFlavor(clipboard, NULL, kUTTypePNG, data, 0); CFRelease(clipboard); CFRelease(data); free(pngbuf); return 0; } 

我有兴趣将这个function移植到Linux / * BSD平台上。 我怎样才能复制这个使用X?

Solutions Collecting From Web of "如何用X11复制到剪贴板?"

先阅读X Selections,Cut Buffers和Kill Rings 。 X11有一个相当独特的系统,似乎没有人复制。

与大多数其他系统不同的是,如果拥有选择(剪贴板)的程序消失,选择也会消失。 所以当你的程序显示“我有一个选择(恰好是一个图像)”,然后退出,没有人能够从你那里请求该图像的副本。 为了有用,剪贴板所有者至少需要坚持到另一个程序进行选择。

还在? 这是一个简短的程序,使用PyGTK来做你想做的事情(因为C是一个痛苦)。

 #!/usr/bin/env python import gtk import sys count = 0 def handle_owner_change(clipboard, event): global count print 'clipboard.owner-change(%r, %r)' % (clipboard, event) count += 1 if count > 1: sys.exit(0) image = gtk.gdk.pixbuf_new_from_file(sys.argv[1]) clipboard = gtk.clipboard_get() clipboard.connect('owner-change', handle_owner_change) clipboard.set_image(image) clipboard.store() gtk.main() 

发生了什么事情:

  • Gdk加载图像。
  • Gtk声称CLIPBOARD选择的所有权。
  • Gtk 请求 CLIPBOARD_MANAGER复制并进行选择。 (可能没有一个正在运行,所以这可能不会发生。)
  • 当另一个程序从我们的选择中请求数据时,Gtk处理数据从图像到目标的转换和传输。
  • 第一个OWNER_CHANGE事件对应于我们取得所有权; 等待下一个对应于我们失去所有权,并退出。

如果剪贴板管理器正在运行,该程序可能会立即退出。 否则,将等待直到在其他程序中执行“剪切/复制”。

在程序终止后,将数据存储在GTK剪贴板中的能力不被很好的支持。 GTK.clipboard.store可能无法存储更大的图像(大于几百kB),像compiz这样的高级桌面功能可能会与此机制相冲突。 一个没有这些缺点的解决方案是在后台运行一个简单的gtk应用程序。 以下Python服务器应用程序使用Pyro包来公开ImageToClipboard的方法:

 #! /usr/bin/env python # gclipboard-imaged.py import gtk, sys, threading; import Pyro.core; class ImageToClipboard(Pyro.core.ObjBase): def __init__(self, daemon): Pyro.core.ObjBase.__init__(self) self.daemon = daemon; def _set_image(self, img): clp = gtk.clipboard_get(); clp.set_image(img); def set_image_from_filename(self, filename): with gtk.gdk.lock: img = gtk.gdk.pixbuf_new_from_file(filename); self._set_image(img); def quit(self): with gtk.gdk.lock: gtk.main_quit(); self.daemon.shutdown(); class gtkThread( threading.Thread ): def run(self): gtk.main(); def main(): gtk.gdk.threads_init(); gtkThread().start(); Pyro.core.initserver(); daemon = Pyro.core.Daemon(); uri = daemon.connect(ImageToClipboard(daemon),"imagetoclipboard") print "The daemon running on port:",daemon.port print "The object's uri is:",uri daemon.requestLoop(); print "Shutting down." return 0; if __name__=="__main__": sys.exit( main() ) 

开始这个程序作为后台进程,即

gclipboard-imaged.py&

以下示例客户端应用程序使用在命令行中给出的文件名来设置剪贴板图像:

 #! /usr/bin/env python # gclipboard-setimage.py import Pyro.core, sys; serverobj = Pyro.core.getProxyForURI("PYROLOC://localhost:7766/imagetoclipboard"); filename = sys.argv[1]; serverobj.set_image_from_filename(filename); 

要将图像复制到剪贴板,请运行

gclipboard-setimage.py picname.png