Domanda

Utilizzando i quadri su OS X, posso utilizzare il seguente per copiare un PNG al tavolo di montaggio (in C - ovviamente ho potuto utilizzare NSPasteboard con cacao):

#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;
}

Mi interessa porting questa funzionalità per Linux / * BSD piattaforme. Come posso replicare questo usando X?

È stato utile?

Soluzione

X Selezioni, Cut Tamponi, e uccidere anelli prima di ogni altra cosa. X11 ha un sistema piuttosto singolare che nessun altro sembra aver copiato.

Una stranezza che è diverso dalla maggior parte degli altri sistemi: se il programma che possiede la selezione (appunti) se ne va, così fa la selezione. Così, quando il vostro programma dice: "Ho una selezione (che sembra essere un'immagine)" e poi esce, nessuno sarà in grado di richiedere una copia di tale immagine da voi. Per essere utile, il proprietario appunti deve restare almeno fino a quando un altro programma prende la selezione.

Ancora qui? Ecco un breve programma che fa quello che si vuole, utilizzando PyGTK (causa C è un dolore).

#!/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()

Quello che succede sotto il cofano:

  • Gdk carica un'immagine.
  • Gtk rivendica la proprietà della selezione negli appunti.
  • richieste che la copia CLIPBOARD_MANAGER e prendere la selezione. (Non ci potrebbe essere una corsa, quindi questo potrebbe non accadere.)
  • Quando un altro programma richiede dati dalla nostra selezione, Gtk gestisce la conversione e il trasferimento dei dati dall'immagine al bersaglio.
  • Il primo evento OWNER_CHANGE corrisponde a noi prendere possesso; attendere il prossimo quello corrispondente a noi di perdere la proprietà, e l'uscita.

Se un gestore di appunti è in esecuzione, questo programma può uscire immediatamente. In caso contrario, si attenderà fino a che "taglia / copia" viene eseguita in un altro programma.

Altri suggerimenti

La possibilità di memorizzare i dati negli appunti GTK, dopo un programma termina, non è ben supportato. GTK.clipboard.store potrebbe non riuscire a memorizzare le immagini più grandi (maggiori di alcune centinaia kB), e funzioni avanzate del desktop come Compiz può entrare in conflitto con questo meccanismo. Una soluzione senza questi inconvenienti è quello di eseguire una semplice applicazione gtk in background. La seguente applicazione server Python usa il pacchetto Piro per esporre i metodi di 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() )

Avvia il programma come un processo in background, cioè.

gclipboard-imaged.py &

La seguente applicazione esempio client imposta l'immagine appunti utilizzando un nome file data dalla riga di comando:


#! /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);

Per copiare un'immagine negli Appunti, eseguire

gclipboard-setimage.py picname.png

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top