Using the frameworks on OS X, I can use the following to copy a PNG to the pasteboard (in C — obviously I could use NSPasteboard with Cocoa):
#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;
}
I'm interested in porting this functionality to Linux/*BSD platforms. How can I replicate this using X?
Go read X Selections, Cut Buffers, and Kill Rings before anything else. X11 has a rather unique system that nobody else seems to have copied.
One oddity that is different from most other systems: if the program owning the selection (clipboard) goes away, so does the selection. So when your program says "I have a selection (which happens to be an image)" and then exits, nobody will be able to request a copy of that image from you. In order to be useful, the clipboard owner needs to stick around at least until another program takes the selection.
Still here? Here's a short program that does what you want, using PyGTK (because C is a pain).
#!/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()
What happens under the hood:
If a clipboard manager is running, this program may exit immediately. Otherwise, it will wait until "cut/copy" is performed in another program.