Hướng dẫn get clipboard python - lấy con trăn vào khay nhớ tạm

Cấu hình

Clipboard là một phần của quản lý cửa sổ chứ không phải của chính hệ điều hành Linux. Các cấu hình khác nhau với các phân phối khác nhau hoạt động khác nhau và do đó yêu cầu các biến thể khác nhau. Trong khi đó, Wayland ngày càng trên đường thay thế liên tiếp X, điều đó có nghĩa là có ba cấu hình để xem xét:

  • Chỉ Wayland
  • Wayland cùng với Xwayland (khả năng tương thích với phần mềm X không điều chỉnh)
  • X

Gửi nội dung clipboard

Khi lưu vào bảng tạm, trước tiên hệ thống chỉ thông báo cho người nhận rằng dữ liệu có sẵn cho bảng tạm. Chỉ theo yêu cầu, dữ liệu thực tế được gửi. Do đó, chương trình gửi nội dung đến bảng tạm không phải bị chấm dứt trước khi dữ liệu được chuyển. Tùy thuộc vào môi trường/cấu hình, cũng có thể nội dung của bảng tạm bị xóa ngay khi chương trình bị chấm dứt.

Làm thế nào sau đó chương trình xclip đã được đề cập trong câu hỏi hoạt động? Nó dường như chấm dứt ngay sau khi được gọi. Nhưng khi kiểm tra kỹ hơn, nó không, bởi vì nó thực hiện một ngã ba, do đó nó vẫn có mặt trong nền (dễ dàng được kiểm chứng bằng cách nhìn vào mã nguồn hoặc lệnh ps).

Định dạng

Hơn nữa, các môi trường khác nhau đòi hỏi nội dung theo những cách khác nhau. Ví dụ: Gnome yêu cầu danh sách các tệp được sao chép với mục tiêu đặc biệt x-special/gnome-copied-files và định dạng đặc biệt của nội dung, ví dụ: copy\nfile:///etc/group cho Trình quản lý tệp Gnome Nautilus để thực hiện chính xác thao tác sao chép.

Theo KDE, mặt khác, sau đó chỉ có một danh sách URI với mục tiêu text/uri-list.

Xác định môi trường

Chương trình ví dụ sau đây hoạt động cho Linuxmint 20.2 Cinnamon, Ubuntu 22.04 với Gnome và Kubuntu 22.04 với KDE. Các phân phối / cấu hình khác có thể yêu cầu một số tùy chỉnh. Ở đây nên chỉ cần sao chép một tệp trong trình quản lý tệp thích hợp và sau đó xem nội dung clipboard bằng một chương trình và sau đó thực hiện các thích ứng phù hợp với tập lệnh.

Dựa trên các biến môi trường

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
0 và
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
1, chương trình sau cố gắng xác định môi trường.

Nếu đó là Wayland,

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
2 được sử dụng, nếu không xclip được sử dụng. Mục tiêu và định dạng nội dung được điều chỉnh phù hợp. Với

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
1, công cụ được khởi động và nội dung được gửi đến
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
2 của công cụ.

Ngay khi điều này được thực hiện, chương trình thoát ra. Cả

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
2 và xclip sau đó tạo một ngã ba, đảm bảo rằng dữ liệu có mặt trong bảng tạm.

import os
import subprocess
import sys
from pathlib import Path

gnome_desktops = ['X-Cinnamon', 'XFCE']


def is_gnome(desktop):
    if desktop.endswith("GNOME") or desktop in gnome_desktops:
        return True
    return False


def target():
    current_desktop = os.environ['XDG_CURRENT_DESKTOP']
    if is_gnome(current_desktop):
        return 'x-special/gnome-copied-files'
    elif current_desktop == 'KDE':
        return 'text/uri-list'
    else:
        sys.exit(f'unsupported desktop {current_desktop}')


def base_copy_cmd():
    if 'WAYLAND_DISPLAY' in os.environ:
        return 'wl-copy'
    return 'xclip -i -selection clipboard'


def copy_clipboard_cmd():
    return f"{base_copy_cmd()} -t '{target()}'"


def content(files_to_copy):
    uris = '\n'.join([Path(f).as_uri() for f in files_to_copy])
    current_desktop = os.environ['XDG_CURRENT_DESKTOP']
    if is_gnome(current_desktop):
        return f"copy\n{uris}".encode("utf-8")
    return uris.encode("utf-8")


def copy_to_clipboard(files_to_copy):
    copy_process = subprocess.Popen(copy_clipboard_cmd(), shell=True, stdin=subprocess.PIPE)
    copy_process.stdin.write(content(files_to_copy))
    copy_process.stdin.close()
    copy_process.wait()


if __name__ == '__main__':
    files = ['/etc/hosts', '/etc/group']
    copy_to_clipboard(files)

Như đã đề cập ở trên cho các môi trường khác, chỉ cần sao chép một tệp trong trình quản lý tệp gốc và sau đó kiểm tra nội dung bảng tạm hiện và thực hiện các điều chỉnh phù hợp với tập lệnh.

Tùy thuộc vào môi trường, xclip hoặc

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
2 (cài đặt gói

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
7 với trình quản lý gói của bạn) phải ở đó. Thông tin chi tiết về
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)
2 có thể được tìm thấy ở đây: https://github.com/bugaevc/wl-clipboard.

Kiểm tra clipboard

Cuối cùng, để có thể đổ các nội dung hiện tại của bảng tạm, đây là một kịch bản nhỏ làm điều đó. Vì vậy, có thể xem những chương trình khác như trình quản lý tệp gốc đặt vào bảng tạm. Thông thường nhiều chương trình đặt một số mục tiêu đại diện khác nhau của cùng một dữ liệu vào bảng tạm.

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk


def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    win.set_title("GTK Clipboard Util")
    win.set_default_size(256, 192)
    btn = Gtk.Button(label="Dump Clipboard")
    btn.connect('clicked', dump)
    box = Gtk.VBox()
    win.add(box)
    box.add(btn)
    win.show_all()


def dump(button):
    cb_targets = []
    counter = 0

    def print_content(clipboard, data):
        print(data.get_data())
        print()
        print_next_target_and_content(clipboard)

    def print_next_target_and_content(clipboard):
        nonlocal counter
        if counter < len(cb_targets):
            target = cb_targets[counter]
            print(target)
            clipboard.request_contents(target, print_content)
            counter += 1

    def get_targets(clipboard, targets, n_targets):
        nonlocal counter
        nonlocal cb_targets
        counter = 0
        cb_targets = targets
        print_next_target_and_content(clipboard)

    gtk_clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
    gtk_clipboard.request_targets(get_targets)


if __name__ == '__main__':
    app = Gtk.Application(application_id='com.software7.clipboard.formats')
    app.connect('activate', on_activate)
    app.run(None)