По запросу я предоставляю пример записи URI в буфер обмена и получения URI из буфера обмена.Эти примеры в основном программы командной строки, которые сразу же получают / устанавливают буфер обмена.В реальном приложении с графическим интерфейсом вы, вероятно, отреагируете на нажатие кнопки или, чтобы поймать Ctrl C / Ctrl V события, используйте Gtk.Widget.add_events()
и получить / установить буфер обмена при обработке сигнала Gtk.Widget.event
.
Получение буфера обмена
Вы можете запросить URI из буфера обмена X11, используя Gtk.Clipboard.request_uris ()
.Эта функция принимает обратный вызов, который будет вызываться после того, как станут доступны URI.
Пример:
public void main (string[] args) {
Gtk.init (ref args);
Gdk.Display display = Gdk.Display.get_default ();
Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);
clipboard.request_uris (recieved_func);
Gtk.main ();
}
/* Gtk.ClipboardURIRecievedFunc */
private void recieved_func (Gtk.Clipboard clipboard, string[] uris) {
foreach (var uri in uris) {
print (uri + "\n");
}
Gtk.main_quit ();
}
Для компиляции с valac clipget.vala --pkg=gtk+-3.0
Настройка буфера обмена
Теория:
Из документации Qt4 :
Поскольку не существует стандартного способа копирования и вставки файлов между приложениями на X11, различные MIMEтипы и соглашения в настоящее время используются.Например, Nautilus ожидает, что файлы будут снабжены MIME-типом x-special / gnome-copied-files с данными, начинающимися с действия вырезания / копирования, символом новой строки и URL-адресом файла.
Gtk.Clipboard
не предусматривает предварительную настройку буфера обмена для копирования / вырезания файлов.Как вы сказали, такого Gtk.Clipboard.set_uris()
.
нет. Вместо этого вы должны установить буфер обмена, предоставив обратный вызов, чтобы X11 получал содержимое буфера обмена после запроса.
Это необходимые шаги:
Создайте группу Gtk.TargetEntry
s, которые определяют, какие протоколы буфера обмена могут обрабатывать ваше приложение.Вы захотите обработать протоколы text/uri-list
, x-special/gnome-copied-files
и UTF8_STRING
.Каждый TargetEntry
идентифицируется своим полем info
, поэтому номер должен быть уникальным (см. enum ClipboardProtocol
в приведенном ниже примере)
Реализуйте метод типа Gtk.ClipboardGetFunc
,Этот метод должен заполнить объект Gtk.SelectionData
, который передается путями файла для копирования / вырезания.Проверьте параметр info
для установки аргумента SelectionData в соответствии с указанным протоколом.
Зарегистрируйте обратный вызов и протоколы, реализованные для X11, используя Gtk.Clipboard.set_with_owner
или Gtk.Clipboard.set_with_data
Пример:
enum ClipboardProtocol {
TEXT_URI_LIST,
GNOME_COPIED_FILES,
UTF8_STRING
}
public void main (string[] args) {
Gtk.init (ref args);
Gdk.Display display = Gdk.Display.get_default ();
Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);
var clipboard_targets = new Gtk.TargetEntry[3];
Gtk.TargetEntry target_entry = { "text/uri-list", 0, ClipboardProtocol.TEXT_URI_LIST };
clipboard_targets[0] = target_entry;
target_entry = { "x-special/gnome-copied-files", 0, ClipboardProtocol.GNOME_COPIED_FILES };
clipboard_targets[1] = target_entry;
target_entry = { "UTF8_STRING", 0, ClipboardProtocol.UTF8_STRING };
clipboard_targets[2] = target_entry;
var owner = new Object ();
var rc = clipboard.set_with_owner (
clipboard_targets,
get_func,
clear_func,
owner
);
assert (rc);
clipboard.store ();
Gtk.main ();
}
/* Gtk.ClipboardGetFunc */
private void get_func (
Gtk.Clipboard clipboard,
Gtk.SelectionData selection_data,
uint info,
void* user_data_or_owner
) {
print ("GET FUNC!\n");
File my_file = File.new_for_path ("/home/lukas/tmp/test.txt");
File my_2nd_file = File.new_for_path ("/home/lukas/tmp/test2.txt");
File[] files = { my_file, my_2nd_file };
switch (info) {
case ClipboardProtocol.TEXT_URI_LIST:
string[] uris = {};
foreach (var file in files) {
uris += file.get_uri ();
}
selection_data.set_uris (uris);
break;
case ClipboardProtocol.GNOME_COPIED_FILES:
var prefix = "copy\n";
//var prefix = "cut\n";
/* use one of the above */
var builder = new StringBuilder (prefix);
for (int i = 0; i < files.length; i++) {
builder.append (files[i].get_uri ());
/* dont put the newline if this is the last file */
if (i != files.length - 1)
builder.append_c ('\n');
}
selection_data.set (
selection_data.get_target (),
8,
builder.data
);
break;
case ClipboardProtocol.UTF8_STRING:
var builder = new StringBuilder ();
foreach (var file in files) {
builder.append (file.get_parse_name ());
}
builder.append_c ('\n');
selection_data.set_text (builder.str, -1);
break;
default:
assert_not_reached ();
}
Gtk.main_quit ();
}
/* Gtk.ClipboardClearFunc */
private void clear_func (Gtk.Clipboard clipboard, void* data) {
;
}
Для компиляции с valac clipset.vala --pkg=gtk+-3.0
Пара примечаний:
В моем примере я мог только протестировать x-special/gnome-copied-files
, так как на данный момент у меня установлен только Nautilus.Я адаптировал все протоколы из исходного кода Thunar (см. Источники ниже), но они могут по-прежнему требовать устранения неполадок *
Если вы не хотите испытывать проблемы с реализацией этого самостоятельно,Вы также можете использовать инструмент командной строки xclip: https://askubuntu.com/a/210428/345569 Однако, IMHO, реализующий это самостоятельно, немного элегантнее.
Источники: