Как скопировать в буфер обмена с X11?

Я не соглашаюсь, что решето Atkin является способом пойти, потому что могло легко занять больше времени регистрировать каждое число [1, n] для простоты чисел, чем это будет для сокращения количества подразделениями.

Вот некоторый код, который, хотя немного hackier, обычно намного быстрее:

import operator
# A slightly efficient superset of primes.
def PrimesPlus():
  yield 2
  yield 3
  i = 5
  while True:
    yield i
    if i % 6 == 1:
      i += 2
    i += 2
# Returns a dict d with n = product p ^ d[p]
def GetPrimeDecomp(n):
  d = {}
  primes = PrimesPlus()
  for p in primes:
    while n % p == 0:
      n /= p
      d[p] = d.setdefault(p, 0) + 1
    if n == 1:
      return d
def NumberOfDivisors(n):
  d = GetPrimeDecomp(n)
  powers_plus = map(lambda x: x+1, d.values())
  return reduce(operator.mul, powers_plus, 1)

ps Это работает код Python для решения этой проблемы.

8
задан Michael 8 December 2009 в 19:30
поделиться

2 ответа

Прежде всего прочтите 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 соответствует тому, что мы становимся владельцем; дождитесь следующего, соответствующего нашей потере права собственности, и выйдите.

Если запущен менеджер буфера обмена, эта программа может немедленно выйти. В противном случае он будет ждать, пока "вырезание / копирование" не будет выполнено в другой программе.

10
ответ дан 5 December 2019 в 14:03
поделиться

Возможность сохранять данные в буфере обмена GTK после завершения программы не поддерживается. GTK.clipboard.store может не хранить изображения большего размера (более нескольких сотен КБ), а расширенные функции рабочего стола, такие как 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

2
ответ дан 5 December 2019 в 14:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: