Pregunta

El uso de los marcos en OS X, puedo usar lo siguiente para copiar un archivo PNG a la mesa de trabajo (en C - obviamente que podría utilizar 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;
}

Estoy interesado en portar esta funcionalidad para Linux / * BSD plataformas. ¿Cómo puedo replicar esta usando X?

¿Fue útil?

Solución

X Selecciones, Cut tampones y anillos Kill antes que nada. X11 tiene un sistema bastante singular que nadie más parece haber copiado.

Una rareza que es diferente de la mayoría de los otros sistemas: si el programa de la posesión de la selección (portapapeles) desaparece, también lo hace la selección. Así que cuando su programa dice "tengo una selección (que pasa a ser una imagen)" y luego se cierra, nadie será capaz de solicitar una copia de esa imagen de usted. Con el fin de ser útil, el propietario del portapapeles tiene que quedarse por lo menos hasta que otro programa se lleva a la selección.

Todavía aquí? He aquí un programa corto que hace lo que quiere, usando PyGTK (porque C es un dolor).

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

Lo que pasa bajo el capó:

  • Gdk carga una imagen.
  • Gtk reclama la propiedad de la selección portapapeles.
  • solicitudes que la copia CLIPBOARD_MANAGER y toman la selección. (Puede que no haya uno corriendo, así que esto podría no suceder.)
  • Cuando otro programa solicita los datos de nuestra selección, GTK se encarga de la conversión y la transferencia de los datos de la imagen a la meta.
  • El primer evento OWNER_CHANGE corresponde a nosotros tomar la propiedad; esperar a la siguiente que corresponde a nosotros perder la propiedad, y salir.

Si un gestor de portapapeles está en funcionamiento, este programa puede salir de inmediato. De lo contrario, se va a esperar hasta que "cortar / copiar" se lleva a cabo en otro programa.

Otros consejos

La capacidad de almacenar datos en el portapapeles GTK después de un programa termina no está bien soportado. GTK.clipboard.store puede fallar para almacenar las imágenes más grandes (de más de varios cientos de KB) y funciones de escritorio avanzadas como compiz puede entrar en conflicto con este mecanismo. Una solución sin estos inconvenientes es ejecutar una aplicación GTK simple en el fondo. La siguiente aplicación de servidor Python utiliza el paquete Pyro para exponer los métodos de 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() )

Iniciar este programa como un proceso en segundo plano, es decir.

gclipboard-imaged.py y

En el siguiente ejemplo de aplicación de cliente establece la imagen del portapapeles utilizando un nombre de archivo dado en la línea de comandos:


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

Para copiar una imagen en el portapapeles, ejecute

gclipboard-setimage.py picname.png

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top