10

OS Xのフレームワークを使用して、次を使用してPNGをペーストボードにコピーできます(Cでは-明らかにNSPasteboardを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;
}

この機能をLinux/*BSDプラットフォームに移植することに興味があります。Xを使用してこれを複製するにはどうすればよいですか?

4

2 に答える 2

10

何よりもまず、Xセレクション、カットバッファー、キルリングを読んでください。X11には、他の誰もコピーしていないように見える、かなりユニークなシステムがあります。

他のほとんどのシステムとは異なる奇妙な点が1つあります。選択範囲(クリップボード)を所有しているプログラムがなくなると、選択範囲もなくなります。したがって、プログラムに「選択範囲があります(これはたまたま画像です)」と表示されて終了すると、誰もその画像のコピーを要求できなくなります。クリップボードの所有者が役立つためには、少なくとも別のプログラムが選択を行うまで、クリップボードの所有者は固執する必要があります。

まだここ?これは、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イベントは、私たちが所有権を取得することに対応しています。私たちに対応する次のものが所有権を失うのを待って、終了します。

クリップボードマネージャが実行されている場合、このプログラムはすぐに終了する場合があります。それ以外の場合は、別のプログラムで「カット/コピー」が実行されるまで待機します。

于 2009-12-08T21:11:36.287 に答える
3

プログラムの終了後にGTKクリップボードにデータを保存する機能は十分にサポートされていません。GTK.clipboard.storeは、より大きな画像(数百kBを超える)の保存に失敗する可能性があり、compizなどの高度なデスクトップ機能がこのメカニズムと競合する可能性があります。これらの欠点のない1つの解決策は、バックグラウンドで単純な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

于 2010-08-08T21:14:23.053 に答える